Skip to content

Instantly share code, notes, and snippets.

@JerryNixon
Last active January 20, 2021 23:56
Show Gist options
  • Select an option

  • Save JerryNixon/c4e92bb4b27f9b9468a1598d05d881a9 to your computer and use it in GitHub Desktop.

Select an option

Save JerryNixon/c4e92bb4b27f9b9468a1598d05d881a9 to your computer and use it in GitHub Desktop.
TSQL version of Floyd-Warshall
IF (object_id('Matrix') is not null)
DROP TABLE Matrix;
GO
CREATE TABLE Matrix
(
SOURCE VARCHAR(50)
, DEST VARCHAR(50)
, COST MONEY
)
GO
IF (object_id('PrintMatrix') is not null)
DROP PROC PrintMatrix;
GO
CREATE PROC PrintMatrix AS
SELECT * FROM [Matrix] PIVOT (SUM([COST])
FOR DEST IN ([A], [B], [C], [D], [E])) AS PivotTable
GO
IF (object_id('FloydWarshall') is not null)
DROP PROC FloydWarshall;
GO
CREATE PROC FloydWarshall AS
BEGIN
DECLARE @K VARCHAR(50);
DECLARE @I VARCHAR(50);
DECLARE @J VARCHAR(50);
DECLARE @infinity INT = 1000000;
SET NOCOUNT ON
DECLARE KCursor CURSOR READ_ONLY FOR
WITH NODES (NODE) AS
(
SELECT [SOURCE] FROM Matrix
UNION SELECT [DEST] FROM Matrix
)
SELECT
N1.NODE AS K
, N2.NODE AS I
, N3.NODE AS J
FROM NODES N1
CROSS JOIN NODES N2
CROSS JOIN NODES N3
WHERE N2.NODE != N3.NODE
ORDER BY 1, 2, 3
OPEN KCursor
FETCH NEXT FROM KCursor INTO @K, @I, @J
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CAST(@K AS VARCHAR(1)) + CAST(@I AS VARCHAR(1)) + CAST(@J AS VARCHAR(1))
UPDATE IJ SET COST = IK.COST + KJ.COST
FROM Matrix AS IJ
LEFT JOIN Matrix AS KJ
ON KJ.SOURCE = @K AND KJ.DEST = @J AND KJ.COST IS NOT NULL
LEFT JOIN Matrix AS IK
ON IK.SOURCE = @I AND IK.DEST = @K AND IK.COST IS NOT NULL
WHERE IJ.SOURCE = @I AND IJ.DEST = @J
AND ISNULL(IJ.COST, @infinity) > IK.COST + KJ.COST
FETCH NEXT FROM KCursor INTO @K, @I, @J
END
CLOSE KCursor;
DEALLOCATE KCursor;
END
GO
INSERT INTO Matrix VALUES
('A', 'A', NULL)
,('A', 'B', 10)
,('A', 'C', 01)
,('A', 'D', 10)
,('A', 'E', 10)
,('B', 'A', NULL)
,('B', 'B', NULL)
,('B', 'C', 10)
,('B', 'D', 01)
,('B', 'E', 10)
,('C', 'A', 01)
,('C', 'B', 01)
,('C', 'C', NULL)
,('C', 'D', 10)
,('C', 'E', 10)
,('D', 'A', NULL)
,('D', 'B', 10)
,('D', 'C', 10)
,('D', 'D', NULL)
,('D', 'E', 01)
,('E', 'A', NULL)
,('E', 'B', 10)
,('E', 'C', 10)
,('E', 'D', 10)
,('E', 'E', NULL);
GO
EXEC PrintMatrix
EXEC FloydWarshall;
EXEC PrintMatrix
GO
DROP PROC FloydWarshall
DROP PROC PrintMatrix
DROP TABLE Matrix
@JerryNixon

Copy link
Copy Markdown
Author

Sample results:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment