SQL Server 2008R2 从 Table 到 Graph 的边缘
SQL Server 2008R2 from Table to edges for Graph
我偶然发现了一个有趣的挑战。我在 SQL 服务器 table 中有以下 format/content.
数据
Date | Name
---------+---------
1/1/2010 | John
1/1/2010 | Mark
1/1/2010 | Peter
1/1/2010 | Mia
2/4/2010 | John
2/4/2010 | Billy
我正在尝试将 table 转换为包含图形边的文件。
我需要边缘文件来包含 table 显示的列和所有组合。
John | Mark
John | Peter
John | Mia
Mark | Mia
Mark | Peter
Peter | Mia
John | Billy
我怀疑这部分可以通过 pivot/unpivot 实现,但不知道如何继续将数据透视表限制为仅两列。
此外,我不知道如何确保我得到所有可能的节点组合,看到前四个 'nodes' 需要变成六个 'edges.'
您可以使用 ROW_NUMBER
和 "triangle join":
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY date ORDER BY Name)
FROM tab
)
SELECT c.Name, c2.Name
FROM cte c
JOIN cte c2
ON c.Date = c2.Date
AND c.rn < c2.rn;
输出:
╔═══════╦═══════╗
║ Name ║ Name ║
╠═══════╬═══════╣
║ John ║ Mark ║
║ John ║ Mia ║
║ John ║ Peter ║
║ Mark ║ Mia ║
║ Mark ║ Peter ║
║ Mia ║ Peter ║ -- ORDER BY based on `Name`
║ Billy ║ John ║ -- same here `B` before `J`
╚═══════╩═══════╝
注:
要获得稳定的排序,您需要添加列以指示具有相同 date
的组内的顺序。我使用 Name
但它交换了最后两行中的名称。
带有 ID
列的版本:
CREATE TABLE tab(ID INT IDENTITY(1,1)
,Date DATE NOT NULL
,Name VARCHAR(6) NOT NULL);
INSERT INTO tab(Date,Name)
VALUES ('1/1/2010','John'), ('1/1/2010','Mark'), ('1/1/2010','Peter')
,('1/1/2010','Mia'), ('2/4/2010','John'),('2/4/2010','Billy');
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY date ORDER BY ID)
FROM tab
)
SELECT c.Name, c2.Name
FROM cte c
JOIN cte c2
ON c.Date = c2.Date
AND c.rn < c2.rn;
输出:
╔═══════╦═══════╗
║ Name ║ Name ║
╠═══════╬═══════╣
║ John ║ Mark ║
║ John ║ Peter ║
║ John ║ Mia ║
║ Mark ║ Peter ║
║ Mark ║ Mia ║
║ Peter ║ Mia ║
║ John ║ Billy ║
╚═══════╩═══════╝
我偶然发现了一个有趣的挑战。我在 SQL 服务器 table 中有以下 format/content.
数据Date | Name
---------+---------
1/1/2010 | John
1/1/2010 | Mark
1/1/2010 | Peter
1/1/2010 | Mia
2/4/2010 | John
2/4/2010 | Billy
我正在尝试将 table 转换为包含图形边的文件。
我需要边缘文件来包含 table 显示的列和所有组合。
John | Mark
John | Peter
John | Mia
Mark | Mia
Mark | Peter
Peter | Mia
John | Billy
我怀疑这部分可以通过 pivot/unpivot 实现,但不知道如何继续将数据透视表限制为仅两列。
此外,我不知道如何确保我得到所有可能的节点组合,看到前四个 'nodes' 需要变成六个 'edges.'
您可以使用 ROW_NUMBER
和 "triangle join":
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY date ORDER BY Name)
FROM tab
)
SELECT c.Name, c2.Name
FROM cte c
JOIN cte c2
ON c.Date = c2.Date
AND c.rn < c2.rn;
输出:
╔═══════╦═══════╗
║ Name ║ Name ║
╠═══════╬═══════╣
║ John ║ Mark ║
║ John ║ Mia ║
║ John ║ Peter ║
║ Mark ║ Mia ║
║ Mark ║ Peter ║
║ Mia ║ Peter ║ -- ORDER BY based on `Name`
║ Billy ║ John ║ -- same here `B` before `J`
╚═══════╩═══════╝
注:
要获得稳定的排序,您需要添加列以指示具有相同 date
的组内的顺序。我使用 Name
但它交换了最后两行中的名称。
带有 ID
列的版本:
CREATE TABLE tab(ID INT IDENTITY(1,1)
,Date DATE NOT NULL
,Name VARCHAR(6) NOT NULL);
INSERT INTO tab(Date,Name)
VALUES ('1/1/2010','John'), ('1/1/2010','Mark'), ('1/1/2010','Peter')
,('1/1/2010','Mia'), ('2/4/2010','John'),('2/4/2010','Billy');
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY date ORDER BY ID)
FROM tab
)
SELECT c.Name, c2.Name
FROM cte c
JOIN cte c2
ON c.Date = c2.Date
AND c.rn < c2.rn;
输出:
╔═══════╦═══════╗
║ Name ║ Name ║
╠═══════╬═══════╣
║ John ║ Mark ║
║ John ║ Peter ║
║ John ║ Mia ║
║ Mark ║ Peter ║
║ Mark ║ Mia ║
║ Peter ║ Mia ║
║ John ║ Billy ║
╚═══════╩═══════╝