[英]SQL Server Graph Database - shortest path using multiple edge types
I have done my research on SQL Server GraphDB, but all the contrived examples I've found so far use only a single edge table.我已经对 SQL Server GraphDB 进行了研究,但是到目前为止我发现的所有人为示例都只使用了一个边表。 It's always
Person-friend_of->Person
, for example.例如,它总是
Person-friend_of->Person
。 In my case, I've created a graph of deployed software components in our datacentre, and there are different edges/relationships.就我而言,我在我们的数据中心创建了一个已部署软件组件的图表,并且存在不同的边缘/关系。 Things like
Application-connects_to->SqlDatabase
and Server-hosts->Application
.诸如
Application-connects_to->SqlDatabase
和Server-hosts->Application
。
I want to write a query that will show me the shortest path between any two nodes, regardless of the Edges used.我想编写一个查询,它将向我显示任意两个节点之间的最短路径,而不管使用的边缘如何。 I think if I was using Neo4j, I'd write the
MATCH
as something like:我想如果我使用的是 Neo4j,我会把
MATCH
写成这样:
Server-*->SqlDatabase
Notice the asterisk. Server-*->SqlDatabase
注意星号。
Is there an idiomatic way to do this in SQL Server?在 SQL 服务器中是否有惯用的方法来执行此操作?
Since SQL Server 2019 you can do exactly that using derived tables or views.自 SQL Server 2019 起,您可以使用派生表或视图完全做到这一点。 I couldn't find any official documentation of this feature, but i found a small remark in a video about Bill of Materials .
我找不到任何有关此功能的官方文档,但我在有关材料清单的视频中发现了一个小注释。
edit: They have some links in that video: Github example编辑:他们在该视频中有一些链接: Github 示例
The point is that you use a UNION ALL
of multiple EDGE (or NODE ) tables to serve as one EDGE (or NODE ) table in the MATCH
operator.关键是您使用多个EDGE (或NODE )表的
UNION ALL
来充当MATCH
运算符中的一个EDGE (或NODE )表。
And an example:还有一个例子:
BEGIN TRANSACTION; --if you execute code found on internet without any scrutiny and have "people" table in your database
GO
DROP TABLE IF EXISTS people, knows, killed, likes;
CREATE TABLE people (Name VARCHAR(100)) AS NODE;
CREATE TABLE knows AS EDGE;
CREATE TABLE killed AS EDGE;
CREATE TABLE likes AS EDGE;
INSERT INTO people
(Name)
VALUES
('A'),
('B'),
('C'),
('D'),
('E')
INSERT INTO knows
($from_id, $to_id)
SELECT
knows.$node_id, known.$node_id
FROM
people AS knows,
people AS known
WHERE
knows.Name = 'A' AND known.Name = 'B';
INSERT INTO killed
($from_id, $to_id)
SELECT
killed.$node_id, victim.$node_id
FROM
people AS killed,
people AS victim
WHERE
(killed.Name = 'A' AND victim.Name = 'C')
OR (killed.Name = 'C' AND victim.Name = 'E');
INSERT INTO likes
($from_id, $to_id)
SELECT
likes.$node_id, liked.$node_id
FROM
people AS likes,
people AS liked
WHERE
likes.Name = 'A' AND liked.Name = 'D';
SELECT
P1.Name AS First_in_chain,
LAST_VALUE(P2.Name) WITHIN GROUP (GRAPH PATH) AS Last_in_chain
FROM
people AS P1,
people FOR PATH AS P2,
------------------------------------------------------------------
---------this is a compound of edges
(
SELECT * FROM knows
UNION ALL
SELECT * FROM killed
UNION ALL
SELECT * FROM likes
) FOR PATH AS RELATION
------------------------------------------------------------------
WHERE
MATCH(
SHORTEST_PATH(
P1(-(RELATION)->P2)+
)
)
AND P1.NAME = 'A'
OPTION(RECOMPILE);
DROP TABLE IF EXISTS people, knows, killed, likes;
GO
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.