SHORTEST_PATH (Transact-SQL)
适用于: sql Server 2019 (15.x) 及更高版本
Azure SQL 数据库
Azure SQL 托管实例 Microsoft Fabric 中的 SQL 数据库
指定以递归或重复方式搜索的图形的搜索条件。 SHORTEST_PATH可以在 SELECT 语句中将 MATCH 与图形节点和边缘表配合使用。
最短路径
SHORTEST_PATH函数使你可以找到:
- 两个给定节点/实体之间的最短路径
- 单个源最短路径。。
- 从多个源节点到多个目标节点的最短路径。
它采用任意长度模式作为输入,并返回两个节点之间存在的最短路径。 此函数只能在 MATCH 内使用。 该函数仅返回任意两个给定节点之间的最短路径。 如果存在,则任何源节点和目标节点对之间长度相同的两个或多个最短路径,则函数仅返回遍历期间第一个找到的路径。 只能在SHORTEST_PATH函数内指定任意长度模式。
有关完整语法,请参阅 MATCH (SQL Graph)。
FOR PATH
FOR PATH 必须与 FROM 子句中的任何节点或边缘表名称一起使用,该子句参与任意长度模式。 FOR PATH 告知引擎节点或边缘表返回一个有序集合,该集合表示沿遍历路径的节点或边缘列表。 这些表中的属性不能直接投影到 SELECT 子句中。 若要从这些表投影属性,必须使用图形路径聚合函数。
任意长度模式
此模式包括必须重复遍历的节点和边缘,直到以下任一操作:
- 达到所需的节点。
- 满足模式中指定的最大迭代次数。
支持以下两种模式限定符:
- “+”:重复模式 1 次或多次。 找到最短路径后立即终止。
- {1,n}:重复模式 1到 n 次。 找到最短时间后立即终止。
LAST_NODE
LAST_NODE() 函数允许链接两个任意长度遍历模式。 可在以下情况下使用:
- 查询中使用了多个最短的路径模式,一个模式从上一模式的 LAST 节点开始。
- 两种最短的路径模式在同一LAST_NODE()合并。
图形路径顺序
图形路径顺序是指输出路径中的数据顺序。 输出路径顺序始终从模式的非递归部分开始,后跟递归部分中显示的节点/边缘。 在查询优化/执行期间遍历图形的顺序与输出中打印的顺序无关。 同样,递归模式中的箭头方向也不会影响图形路径顺序。
图形路径聚合函数
由于任意长度模式涉及的节点和边缘返回在该路径中遍历的集合(节点和边缘),因此用户无法使用传统的 tablename.attributename 语法直接投影属性。 对于需要从中间节点或边缘表投影属性值的查询,在遍历的路径中,使用以下图形路径聚合函数:STRING_AGG、LAST_VALUE、SUM、AVG、MIN、MAX 和 COUNT。 在 SELECT 子句中使用这些聚合函数的一般语法是:
<GRAPH_PATH_AGGREGATE_FUNCTION>(<expression> , <separator>) <order_clause>
<order_clause> ::=
{ WITHIN GROUP (GRAPH PATH) }
<GRAPH_PATH_AGGREGATE_FUNCTION> ::=
STRING_AGG
| LAST_VALUE
| SUM
| COUNT
| AVG
| MIN
| MAX
STRING_AGG
STRING_AGG函数采用表达式和分隔符作为输入并返回字符串。 用户可以在 SELECT 子句中使用此函数来投影路径中中间节点或边缘的属性。
LAST_VALUE
若要从遍历路径的最后一个节点投影属性,可以使用LAST_VALUE聚合函数。 提供边缘表别名作为此函数的输入是错误的,只能使用节点表名或别名。
最后一个节点:最后一个节点是指在遍历路径中最后显示的节点,而不考虑 MATCH 谓词中的箭头方向。 例如:MATCH(SHORTEST_PATH(n(-(e)->p)+) )
。 路径中的最后一个节点是上次访问的 P 节点。
在模式中 MATCH(SHORTEST_PATH((n<-(e)-)+p))
,最后一个节点是访问的最后一个 N 节点。
SUM
此函数返回在遍历路径中显示的提供的节点/边缘属性值或表达式的总和。
COUNT
此函数返回路径中指定节点/边缘属性的非 null 值数。 COUNT 函数不支持 *
运算符 - 尝试在 *
语法错误中使用结果。
{ COUNT( <expression> ) <order_clause> }
AVG
返回在遍历路径中显示的提供的节点/边缘属性值或表达式的平均值。
MIN
从提供的节点/边缘属性值或表达式中返回在遍历路径中显示的最小值。
MAX
从提供的节点/边缘属性值或表达式中返回在遍历路径中显示的最大值。
注解
- SHORTEST_PATH函数只能在 MATCH 内使用。
- LAST_NODE函数仅在SHORTEST_PATH内受支持。
- SHORTEST_PATH函数返回 节点之间的任意 最短路径。 它当前不支持返回 节点之间的所有最短路径 ;也不支持返回 节点之间的所有路径 。
- SHORTEST_PATH实现找到一条不加权的最短路径。
- 在某些情况下,可能会为具有较高跃点数的查询生成错误的计划,从而导致查询执行时间较高。 评估查询提示(如 OPTION(HASH JOIN)和/或 OPTION(MAXDOP 1)是否有帮助。
示例
对于此处显示的示例查询,我们使用在 SQL Graph 示例中创建的节点表和边缘表
A. 查找两个人之间的最短路径
在以下示例中,我们发现雅各布和 Alice 之间的最短路径。 我们需要Person
从 SQL Graph 示例创建的节点和friendOf
边缘。
SELECT PersonName, Friends
FROM (
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
LAST_VALUE(Person2.name) WITHIN GROUP (GRAPH PATH) AS LastNode
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
AND Person1.name = 'Jacob'
) AS Q
WHERE Q.LastNode = 'Alice'
B. 查找从给定节点到图中所有其他节点的最短路径。
以下示例查找雅各布在图中连接到的所有人员,以及从雅各布到所有这些人的最短路径。
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
AND Person1.name = 'Jacob'
°C 计算从图中的一个人到另一个人遍历的跃点/级别数。
以下示例查找雅各布和 Alice 之间的最短路径,并打印从雅各布到 Alice 所花费的跃点数。
SELECT PersonName, Friends, levels
FROM (
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
LAST_VALUE(Person2.name) WITHIN GROUP (GRAPH PATH) AS LastNode,
COUNT(Person2.name) WITHIN GROUP (GRAPH PATH) AS levels
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
AND Person1.name = 'Jacob'
) AS Q
WHERE Q.LastNode = 'Alice'
D. 从给定的人中查找 1-3 跃点
下面的示例找到雅各布和雅各布与图中与他相连接的最短路径,即一到三个跃点。
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2){1,3}))
AND Person1.name = 'Jacob'
E. 找到离给定人只有两个跃点的人
以下示例在图中找到雅各布和离他两个跃点的人之间的最短路径。
SELECT PersonName, Friends
FROM (
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
COUNT(Person2.name) WITHIN GROUP (GRAPH PATH) AS levels
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2){1,3}))
AND Person1.name = 'Jacob'
) Q
WHERE Q.levels = 2
F. 找到 1-3 跃点远离给定的人, 谁也喜欢特定的餐厅
以下示例找到雅各布和他与图 1-3 跃点相联系的所有人之间的最短路径。 该查询还通过喜欢给定餐厅来筛选连接人员。 在下面的示例中,返回 LAST_NODE(Person2)
每个最短路径的最终节点。 然后,从LAST_NODE
中获取的“最后一个”Person
节点可以“链接”,以便进一步遍历找到他们喜欢的餐馆。
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
Restaurant.name
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2,
likes,
Restaurant
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2){1,3}) AND LAST_NODE(Person2)-(likes)->Restaurant )
AND Person1.name = 'Jacob'
AND Restaurant.name = 'Ginger and Spice'
G. 查找从给定节点到图中所有其他节点的最短路径,不包括“循环”
以下示例查找 Alice 在关系图中连接到的所有人员,以及从 Alice 到所有这些人的最短路径。 该示例显式检查路径的起始节点和结束节点是否相同。
SELECT PersonName, Friends
FROM (
SELECT
Person1.name AS PersonName,
STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
LAST_VALUE(Person2.name) WITHIN GROUP (GRAPH PATH) AS LastNode
FROM
Person AS Person1,
friendOf FOR PATH AS fo,
Person FOR PATH AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
AND Person1.name = 'Alice'
) AS Q
WHERE Q.LastNode != 'Alice'