sql server: 最短路径
---------------------------------------------------------------------
-- Road System 道路
--------------------------------------------------------------------- -- Listing 9-3: DDL & Sample Data for Cities, Roads
SET NOCOUNT ON;
USE tempdb;
GO
IF OBJECT_ID('dbo.Roads') IS NOT NULL
DROP TABLE dbo.Roads;
GO
IF OBJECT_ID('dbo.Cities') IS NOT NULL
DROP TABLE dbo.Cities;
GO CREATE TABLE dbo.Cities
(
cityid CHAR(3) NOT NULL PRIMARY KEY,
city VARCHAR(30) NOT NULL,
region VARCHAR(30) NULL,
country VARCHAR(30) NOT NULL
); INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('ATL', 'Atlanta', 'GA', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('ORD', 'Chicago', 'IL', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('DEN', 'Denver', 'CO', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('IAH', 'Houston', 'TX', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('MCI', 'Kansas City', 'KS', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('LAX', 'Los Angeles', 'CA', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('MIA', 'Miami', 'FL', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('MSP', 'Minneapolis', 'MN', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('JFK', 'New York', 'NY', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('SEA', 'Seattle', 'WA', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('SFO', 'San Francisco', 'CA', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('ANC', 'Anchorage', 'AK', 'USA');
INSERT INTO dbo.Cities(cityid, city, region, country)
VALUES('FAI', 'Fairbanks', 'AK', 'USA'); CREATE TABLE dbo.Roads
(
city1 CHAR(3) NOT NULL REFERENCES dbo.Cities,
city2 CHAR(3) NOT NULL REFERENCES dbo.Cities,
distance INT NOT NULL,
PRIMARY KEY(city1, city2),
CHECK(city1 < city2),
CHECK(distance > 0)
); INSERT INTO dbo.Roads(city1, city2, distance) VALUES('ANC', 'FAI', 359);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('ATL', 'ORD', 715);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('ATL', 'IAH', 800);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('ATL', 'MCI', 805);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('ATL', 'MIA', 665);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('ATL', 'JFK', 865);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('DEN', 'IAH', 1120);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('DEN', 'MCI', 600);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('DEN', 'LAX', 1025);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('DEN', 'MSP', 915);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('DEN', 'SEA', 1335);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('DEN', 'SFO', 1270);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('IAH', 'MCI', 795);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('IAH', 'LAX', 1550);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('IAH', 'MIA', 1190);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('JFK', 'ORD', 795);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('LAX', 'SFO', 385);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('MCI', 'ORD', 525);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('MCI', 'MSP', 440);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('MSP', 'ORD', 410);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('MSP', 'SEA', 2015);
INSERT INTO dbo.Roads(city1, city2, distance) VALUES('SEA', 'SFO', 815);
GO SELECT * FROM dbo.Roads
GO WITH Roads2 --每对城市生成行
AS
(
SELECT city1 AS from_city,city2 AS to_city FROM dbo.Roads
UNION ALL
SELECT city2,city2 FROM dbo.Roads
),
RoadPaths AS
(
--返回第一级别的所有可到达的城市对
SELECT from_city,to_city,
CAST('.'+from_city+'.'+to_city+'.' AS VARCHAR(max)) AS path
FROM Roads2
UNION ALL
SELECT F.from_city,T.to_city,--返回下一级别的可到达的城市对
CAST(F.path+T.to_city+'.' AS VARCHAR(MAX)) --路径需要验明循环
FROM RoadPaths AS F
JOIN Roads2 AS T
ON CASE WHEN F.path LIKE '%.'+T.to_city+'.%' --如果to_city出现在from_city的路径中,则检测到循环
THEN 1 ELSE 0 END =0
AND F.to_city =T.from_city
)
SELECT DISTINCT from_city,to_city FROM RoadPaths;--返回Roads 的传递包
GO ---------------------------------------------------------------------
-- Undirected Cyclic Graph
--------------------------------------------------------------------- -- Listing 9-38: Transitive Closure of Roads (Undirected Cyclic Graph) 传递闭包
WITH Roads2 -- Two rows for each pair (f-->t, t-->f)
AS
(
SELECT city1 AS from_city, city2 AS to_city FROM dbo.Roads
UNION ALL
SELECT city2, city1 FROM dbo.Roads
),
RoadPaths AS
(
-- Return all first-level reachability pairs
SELECT from_city, to_city,
-- path is needed to identify cycles
CAST('.' + from_city + '.' + to_city + '.' AS VARCHAR(MAX)) AS path
FROM Roads2 UNION ALL -- Return next-level reachability pairs
SELECT F.from_city, T.to_city,
CAST(F.path + T.to_city + '.' AS VARCHAR(MAX))
FROM RoadPaths AS F
JOIN Roads2 AS T
-- if to_city appears in from_city's path, cycle detected
ON CASE WHEN F.path LIKE '%.' + T.to_city + '.%'
THEN 1 ELSE 0 END = 0
AND F.to_city = T.from_city
)
-- Return Transitive Closure of Roads
SELECT DISTINCT from_city, to_city
FROM RoadPaths;
GO -- Listing 9-39: Creation Script for the fn_RoadsTC UDF
IF OBJECT_ID('dbo.fn_RoadsTC') IS NOT NULL
DROP FUNCTION dbo.fn_RoadsTC;
GO CREATE FUNCTION dbo.fn_RoadsTC() RETURNS @RoadsTC TABLE (
from_city VARCHAR(3) NOT NULL,
to_city VARCHAR(3) NOT NULL,
PRIMARY KEY (from_city, to_city)
)
AS
BEGIN
DECLARE @added as INT; INSERT INTO @RoadsTC(from_city, to_city)
SELECT city1, city2 FROM dbo.Roads; SET @added = @@rowcount; INSERT INTO @RoadsTC
SELECT city2, city1 FROM dbo.Roads SET @added = @added + @@rowcount; WHILE @added > 0 BEGIN INSERT INTO @RoadsTC
SELECT DISTINCT TC.from_city, R.city2
FROM @RoadsTC AS TC
JOIN dbo.Roads AS R
ON R.city1 = TC.to_city
WHERE NOT EXISTS
(SELECT * FROM @RoadsTC AS TC2
WHERE TC2.from_city = TC.from_city
AND TC2.to_city = R.city2)
AND TC.from_city <> R.city2; SET @added = @@rowcount; INSERT INTO @RoadsTC
SELECT DISTINCT TC.from_city, R.city1
FROM @RoadsTC AS TC
JOIN dbo.Roads AS R
ON R.city2 = TC.to_city
WHERE NOT EXISTS
(SELECT * FROM @RoadsTC AS TC2
WHERE TC2.from_city = TC.from_city
AND TC2.to_city = R.city1)
AND TC.from_city <> R.city1; SET @added = @added + @@rowcount;
END
RETURN;
END
GO -- Use the fn_RoadsTC UDF --传递闭包函数
SELECT * FROM dbo.fn_RoadsTC();
GO -- Listing 9-40: All paths and distances in Roads (15262 rows)返回所有路径和距离
WITH Roads2
AS
(
SELECT city1 AS from_city, city2 AS to_city, distance FROM dbo.Roads
UNION ALL
SELECT city2, city1, distance FROM dbo.Roads
),
RoadPaths AS
(
SELECT from_city, to_city, distance,
CAST('.' + from_city + '.' + to_city + '.' AS VARCHAR(MAX)) AS path
FROM Roads2 UNION ALL SELECT F.from_city, T.to_city, F.distance + T.distance,
CAST(F.path + T.to_city + '.' AS VARCHAR(MAX))
FROM RoadPaths AS F
JOIN Roads2 AS T
ON CASE WHEN F.path LIKE '%.' + T.to_city + '.%'
THEN 1 ELSE 0 END = 0
AND F.to_city = T.from_city
)
-- Return all paths and distances
SELECT * FROM RoadPaths;
GO -- Listing 9-41: Shortest paths in Roads 返回最短路径
WITH Roads2
AS
(
SELECT city1 AS from_city, city2 AS to_city, distance FROM dbo.Roads
UNION ALL
SELECT city2, city1, distance FROM dbo.Roads
),
RoadPaths AS
(
SELECT from_city, to_city, distance,
CAST('.' + from_city + '.' + to_city + '.' AS VARCHAR(MAX)) AS path
FROM Roads2 UNION ALL SELECT F.from_city, T.to_city, F.distance + T.distance,
CAST(F.path + T.to_city + '.' AS VARCHAR(MAX))
FROM RoadPaths AS F
JOIN Roads2 AS T
ON CASE WHEN F.path LIKE '%.' + T.to_city + '.%'
THEN 1 ELSE 0 END = 0
AND F.to_city = T.from_city
),
RoadsMinDist -- Min distance for each pair in TC 每对城市的最短距离
AS
(
SELECT from_city, to_city, MIN(distance) AS mindist
FROM RoadPaths
GROUP BY from_city, to_city
)
-- Return shortest paths and distances 返回最短路径和距离
SELECT RP.*
FROM RoadsMinDist AS RMD
JOIN RoadPaths AS RP
ON RMD.from_city = RP.from_city
AND RMD.to_city = RP.to_city
AND RMD.mindist = RP.distance;
GO -- Listing 9-42: Load Shortest Road Paths Into a Table 把最短路径保存到表
WITH Roads2
AS
(
SELECT city1 AS from_city, city2 AS to_city, distance FROM dbo.Roads
UNION ALL
SELECT city2, city1, distance FROM dbo.Roads
),
RoadPaths AS
(
SELECT from_city, to_city, distance,
CAST('.' + from_city + '.' + to_city + '.' AS VARCHAR(MAX)) AS path
FROM Roads2 UNION ALL SELECT F.from_city, T.to_city, F.distance + T.distance,
CAST(F.path + T.to_city + '.' AS VARCHAR(MAX))
FROM RoadPaths AS F
JOIN Roads2 AS T
ON CASE WHEN F.path LIKE '%.' + T.to_city + '.%'
THEN 1 ELSE 0 END = 0
AND F.to_city = T.from_city
),
RoadsMinDist
AS
(
SELECT from_city, to_city, MIN(distance) AS mindist
FROM RoadPaths
GROUP BY from_city, to_city
)
SELECT RP.*
INTO dbo.RoadPaths
FROM RoadsMinDist AS RMD
JOIN RoadPaths AS RP
ON RMD.from_city = RP.from_city
AND RMD.to_city = RP.to_city
AND RMD.mindist = RP.distance; CREATE UNIQUE CLUSTERED INDEX idx_uc_from_city_to_city
ON dbo.RoadPaths(from_city, to_city);
GO -- Return shortest path between Los Angeles and New York 测试查询最短路径
SELECT * FROM dbo.RoadPaths
WHERE from_city = 'LAX' AND to_city = 'JFK';
GO -- Listing 9-43: Creation Script for the fn_RoadsTC UDF
IF OBJECT_ID('dbo.fn_RoadsTC') IS NOT NULL
DROP FUNCTION dbo.fn_RoadsTC;
GO
CREATE FUNCTION dbo.fn_RoadsTC() RETURNS @RoadsTC TABLE
(
uniquifier INT NOT NULL IDENTITY,
from_city VARCHAR(3) NOT NULL,
to_city VARCHAR(3) NOT NULL,
distance INT NOT NULL,
route VARCHAR(MAX) NOT NULL,
PRIMARY KEY (from_city, to_city, uniquifier)
)
AS
BEGIN
DECLARE @added AS INT; INSERT INTO @RoadsTC
SELECT city1 AS from_city, city2 AS to_city, distance,
'.' + city1 + '.' + city2 + '.'
FROM dbo.Roads; SET @added = @@rowcount; INSERT INTO @RoadsTC
SELECT city2, city1, distance, '.' + city2 + '.' + city1 + '.'
FROM dbo.Roads; SET @added = @added + @@rowcount; WHILE @added > 0 BEGIN
INSERT INTO @RoadsTC
SELECT DISTINCT TC.from_city, R.city2,
TC.distance + R.distance, TC.route + city2 + '.'
FROM @RoadsTC AS TC
JOIN dbo.Roads AS R
ON R.city1 = TC.to_city
WHERE NOT EXISTS
(SELECT * FROM @RoadsTC AS TC2
WHERE TC2.from_city = TC.from_city
AND TC2.to_city = R.city2
AND TC2.distance <= TC.distance + R.distance)
AND TC.from_city <> R.city2; SET @added = @@rowcount; INSERT INTO @RoadsTC
SELECT DISTINCT TC.from_city, R.city1,
TC.distance + R.distance, TC.route + city1 + '.'
FROM @RoadsTC AS TC
JOIN dbo.Roads AS R
ON R.city2 = TC.to_city
WHERE NOT EXISTS
(SELECT * FROM @RoadsTC AS TC2
WHERE TC2.from_city = TC.from_city
AND TC2.to_city = R.city1
AND TC2.distance <= TC.distance + R.distance)
AND TC.from_city <> R.city1; SET @added = @added + @@rowcount;
END
RETURN;
END
GO -- Return shortest paths and distances
SELECT from_city, to_city, distance, route
FROM (SELECT from_city, to_city, distance, route,
RANK() OVER (PARTITION BY from_city, to_city
ORDER BY distance) AS rk
FROM dbo.fn_RoadsTC()) AS RTC
WHERE rk = 1;
GO -- Cleanup
DROP TABLE dbo.RoadPaths;
GO
sql server: 最短路径的更多相关文章
- 在SQL Server实现最短路径的搜索
开始 这是去年的问题了,今天在整理邮件的时候才发现这个问题,感觉顶有意思的,特记录下来. 在表RelationGraph中,有三个字段(ID,Node,RelatedNode),其中Node和Rela ...
- 【转】T-SQL查询进阶—理解SQL Server中的锁
简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查 ...
- SQL Server中的锁的简单学习
简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的 ...
- T-SQL查询进阶—理解SQL Server中的锁
在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的.这些 ...
- 理解SQL Server中索引的概念
T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他 简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能 ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
- 理解SQL Server中索引的概念,原理
转自:http://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html 简介 在SQL Server中,索引是一种增强式的存在,这意味着, ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,sql server仍然可以实现应有的功能,但索引可以在大多数情况下提升查询性能,在OLAP(On line Trans ...
- 理解SQL Server中索引的概念,原理以及其他(转载)
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
随机推荐
- 枚举类型enum详解——C语言
enum enum是C语言中的一个关键字,enum叫枚举数据类型,枚举数据类型描述的是一组整型值的集合(这句话其实不太妥当),枚举型是预处理指令#define的替代,枚举和宏其实非常类似,宏在预处理阶 ...
- Java 字符串类型常用方法
常用方法 获取字符串长度 public int length() 字符串Unicode操作 这部分用的不多,不是很清楚,先记载在这. //获取指定索引处的元素对应的unciode编码 public i ...
- LeetCode:111_Minimum Depth of Binary Tree | 二叉树的最小深度 | Easy
要求:此题正好和Maximum Depth of Binary Tree一题是相反的,即寻找二叉树的最小的深度值:从根节点到最近的叶子节点的距离. 结题思路:和找最大距离不同之处在于:找最小距离要注意 ...
- win10 + gluon + GPU
1. 下载教程 可以用浏览器下载zip格式并解压,在解压目录文件资源管理器的地址栏输入cmd进入命令行模式. 也可以 git pull https://github.com/mli/gluon-tut ...
- ubuntu里面搭建虚拟环境过程中遇到的问题以及解决方法。
今天开始学习Django,发现要搭建虚拟环境.就按照百度上面的方法在ubuntu中输入终端命名进行配置.发现自己是按照步骤来的.却总是在最后一步启动 source .bashrc 的时候出现''com ...
- Python 离线工作环境搭建
准备 在断网的和联网的机器安装pip,下载地址https://pypi.python.org/pypi/pip 在联网的开发机器上安装好需要的包 例如: pip3 install paramiko p ...
- Python内置类型(1)——真值测试
python中任何对象都能直接进行真假值的测试,用于if或者while语句的条件判断,也可以做为布尔逻辑运算符的操作数 python中任何对象都能直接进行真假值的测试,而不需要额外的类型转换 这一点是 ...
- ArrayList的实现原理
ArrayList的线性复杂度是1.想确定一个数据,直接通过索引进行访问.实际上这个过程和数组是非常相似的.ArrayList在整个使用过程中,如果想要高效操作,最好设置一个数组的大小.在个数固定的情 ...
- SpringBoot之oauth2.0学习之服务端配置快速上手
现在第三方登录的例子数见不鲜.其实在这种示例当中,oauth2.0是使用比较多的一种授权登录的标准.oauth2.0也是从oauth1.0升级过来的.那么关于oauth2.0相关的概念及其原理,大家可 ...
- GNum试用体验
只需在GNum上注册一个用户名,填上自己的电话号码,它就会自动生成一个URL,你的朋友(可以不注册GNum)在浏览器上进入这个 URL,就可以给你的手机打电话,目前可以免费通话200分钟,而且如果你邀 ...