问题描述
我有[朋友]节点和[链接]边缘。我的任务是弄清楚子图(网络)属于哪个朋友。简单说明如下:
这是我的代码,该如何构造节点,边并填充数据:
-- Construct nodes
DROP TABLE IF EXISTS [dbo].[Friend];
CREATE TABLE [dbo].[Friend] (
[FriendId] INT IDENTITY PRIMARY KEY,[Name] NVARCHAR(256) NOT NULL
) AS NODE;
INSERT INTO [dbo].[Friend]([Name]) VALUES
('Jon'),('Rita'),('Ben'),('Andrew'),('Joe'),('Patrick'),('Mike'),('Thomas'),('Kelly'),('Lily'),('Kira');
-- Construct edges
DROP TABLE IF EXISTS [dbo].[Link];
CREATE TABLE [dbo].[Link] (
[LinkDirection] BIT NOT NULL,[FriendIdFrom] INT NOT NULL,[FriendIdTo] INT NOT NULL
)AS EDGE;
INSERT INTO [dbo].[Link] ($from_id,$to_id,[LinkDirection],[FriendIdFrom],[FriendIdTo])
-- Network 1
SELECT [f1].$node_id,[f2].$node_id,1,[f1].[FriendId],[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Jon' AND [f2].[Name] = 'Rita'
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Jon' AND [f2].[Name] = 'Ben'
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Jon' AND [f2].[Name] = 'Andrew'
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Andrew' AND [f2].[Name] = 'Joe'
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Andrew' AND [f2].[Name] = 'Patrick'
-- Network 2
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Mike' AND [f2].[Name] = 'Thomas'
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Mike' AND [f2].[Name] = 'Kelly'
-- Network 3
UNION ALL SELECT [f1].$node_id,[f2].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Lily' AND [f2].[Name] = 'Kira'
-- To have bi-directional link
-- Network 1
UNION ALL SELECT [f2].$node_id,[f1].$node_id,[f2].[FriendId],[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Jon' AND [f2].[Name] = 'Rita'
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Jon' AND [f2].[Name] = 'Ben'
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Jon' AND [f2].[Name] = 'Andrew'
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Andrew' AND [f2].[Name] = 'Joe'
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Andrew' AND [f2].[Name] = 'Patrick'
-- Network 2
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Mike' AND [f2].[Name] = 'Thomas'
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Mike' AND [f2].[Name] = 'Kelly'
-- Network 3
UNION ALL SELECT [f2].$node_id,[f1].[FriendId] FROM [dbo].[Friend] [f1] INNER JOIN [dbo].[Friend] [f2] ON [f1].[Name] = 'Lily' AND [f2].[Name] = 'Kira';
我有代码,如何列出所有可能的路径:
SELECT
[StartNode] = [f1].[Name],[FinalNode] = LAST_VALUE([f2].[name]) WITHIN GROUP (GRAPH PATH),[Steps] = COUNT([f2].[FriendId]) WITHIN GROUP (GRAPH PATH),[Path] = [f1].[Name] + ' => ' + STRING_AGG([f2].[Name],' => ') WITHIN GROUP (GRAPH PATH),[Network] = '???'
--,*
FROM
[dbo].[Friend] [f1],[dbo].[Friend] FOR PATH [f2],[dbo].[Link] FOR PATH [l]
WHERE
MATCH(SHORTEST_PATH(f1(-(l)->f2)+));
但是,我在如何在此处添加网络标识符(唯一的数字,文本,无关紧要)方面很费劲:( 也许有人曾经有过经验,可以提供帮助吗?
预期结果是:
---------------------------------------------------------------------------------
|StartNode | FinalNode | Steps | Path |Network|
|------------| -----------| -------| -----------------------------------|-------|
|Jon | Rita | 1 | Jon => Rita |1 |
|Jon | Ben | 1 | Jon => Ben |1 |
|Jon | Andrew | 1 | Jon => Andrew |1 |
|Rita | Jon | 1 | Rita => Jon |1 |
|Ben | Jon | 1 | Ben => Jon |1 |
|Andrew | Jon | 1 | Andrew => Jon |1 |
|Andrew | Joe | 1 | Andrew => Joe |1 |
|Andrew | Patrick | 1 | Andrew => Patrick |1 |
|Joe | Andrew | 1 | Joe => Andrew |1 |
|Patrick | Andrew | 1 | Patrick => Andrew |1 |
|Mike | Thomas | 1 | Mike => Thomas |2 |
|Mike | Kelly | 1 | Mike => Kelly |2 |
|Thomas | Mike | 1 | Thomas => Mike |2 |
|Kelly | Mike | 1 | Kelly => Mike |2 |
|Lily | Kira | 1 | Lily => Kira |3 |
|Kira | Lily | 1 | Kira => Lily |3 |
|Jon | Jon | 2 | Jon => Andrew => Jon |1 |
|Jon | Joe | 2 | Jon => Andrew => Joe |1 |
|Jon | Patrick | 2 | Jon => Andrew => Patrick |1 |
|Rita | Rita | 2 | Rita => Jon => Rita |1 |
|Rita | Ben | 2 | Rita => Jon => Ben |1 |
|Rita | Andrew | 2 | Rita => Jon => Andrew |1 |
|Ben | Rita | 2 | Ben => Jon => Rita |1 |
|Ben | Ben | 2 | Ben => Jon => Ben |1 |
|Ben | Andrew | 2 | Ben => Jon => Andrew |1 |
|Andrew | Rita | 2 | Andrew => Jon => Rita |1 |
|Andrew | Ben | 2 | Andrew => Jon => Ben |1 |
|Andrew | Andrew | 2 | Andrew => Jon => Andrew |1 |
|Joe | Jon | 2 | Joe => Andrew => Jon |1 |
|Joe | Joe | 2 | Joe => Andrew => Joe |1 |
|Joe | Patrick | 2 | Joe => Andrew => Patrick |1 |
|Patrick | Jon | 2 | Patrick => Andrew => Jon |1 |
|Patrick | Joe | 2 | Patrick => Andrew => Joe |1 |
|Patrick | Patrick | 2 | Patrick => Andrew => Patrick |1 |
|Mike | Mike | 2 | Mike => Thomas => Mike |2 |
|Thomas | Thomas | 2 | Thomas => Mike => Thomas |2 |
|Thomas | Kelly | 2 | Thomas => Mike => Kelly |2 |
|Kelly | Thomas | 2 | Kelly => Mike => Thomas |2 |
|Kelly | Kelly | 2 | Kelly => Mike => Kelly |2 |
|Lily | Lily | 2 | Lily => Kira => Lily |3 |
|Kira | Kira | 2 | Kira => Lily => Kira |3 |
|Rita | Joe | 3 | Rita => Jon => Andrew => Joe |1 |
|Rita | Patrick | 3 | Rita => Jon => Andrew => Patrick |1 |
|Ben | Joe | 3 | Ben => Jon => Andrew => Joe |1 |
|Ben | Patrick | 3 | Ben => Jon => Andrew => Patrick |1 |
|Joe | Rita | 3 | Joe => Andrew => Jon => Rita |1 |
|Joe | Ben | 3 | Joe => Andrew => Jon => Ben |1 |
|Patrick | Rita | 3 | Patrick => Andrew => Jon => Rita |1 |
|Patrick | Ben | 3 | Patrick => Andrew => Jon => Ben |1 |
---------------------------------------------------------------------------------
简而言之,我需要一种方法来赋予这些网络唯一的名称,并与人进行映射。
解决方法
select *,min([FinalNode]) over(partition by [StartNode]) as NetworkOf,----in case of duplicate names,also use partition by StartNodeId instead of [StartNode]...
min(FinalFriendId) over(partition by [StartNode]) as NetworkId
from
(
SELECT
[StartNode] = [f1].[Name],[FinalNode] = LAST_VALUE([f2].[name]) WITHIN GROUP (GRAPH PATH),[Steps] = COUNT([f2].[FriendId]) WITHIN GROUP (GRAPH PATH),[Path] = [f1].[Name] + ' => ' + STRING_AGG([f2].[Name],' => ') WITHIN GROUP (GRAPH PATH),FinalFriendId = LAST_VALUE(f2.FriendId) WITHIN GROUP (GRAPH PATH)
FROM
[dbo].[Friend] [f1],[dbo].[Friend] FOR PATH [f2],[dbo].[Link] FOR PATH [l]
WHERE
MATCH(SHORTEST_PATH(f1(-(l)->f2)+))
) as src;