基于非唯一订单号的父子层次结构
Parent child Hierarchy based on non unique order number
我有一个 table 包含系统和订单号列,但不是 unique.I 我想根据订单号连接系统
+----------------------+
¦ system ¦OrderNo¦
¦--------------+-------+
¦ system1 ¦ 1 ¦
¦ system2 ¦ 2 ¦
¦ system3 ¦ 3 ¦
¦ system4 ¦ 4 ¦
¦ system1 ¦ 1 ¦
¦ system2 ¦ 2 ¦
¦ system5 ¦ 1 ¦
¦ system6 ¦ 2 ¦
¦ system7 ¦ 1 ¦
¦ system8 ¦ 2 ¦
+----------------------+
如何根据 OrderNo 列生成父子关系。其中1-2-3-4是一组,1-2,1-2,1-2是另一组
想要的输出如下
+----------------------+
¦ Parent ¦Child ¦
¦--------------+-------+
¦ system1 ¦system2¦
¦ system2 ¦system3¦
¦ system3 ¦system4¦
¦ system4 ¦NULL ¦
¦ system1 ¦system2¦
¦ system2 ¦NULL ¦
¦ system5 ¦system6¦
¦ system6 ¦NULL ¦
¦ system7 ¦system8¦
¦ system8 ¦NULL ¦
+----------------------+
正如我在评论中提到的,如果这些是您仅有的专栏,那么您所追求的是无法实现的。如果没有某种升序唯一键,您就无法确定这种关系。如果我们做添加一个唯一的升序键然后我们可以实现这个。
如果您使用的是 SQL Server 2012+(2008 不受支持,扩展支持即将结束,因此升级现在应该是一个非常高的优先级),那么您可以生成您的岛屿使用 ROWS BETWEEN
然后使用 LEAD
:
CREATE TABLE dbo.SampleTable (ID int IDENTITY(1,1),
[system] varchar(8),
OrderNo int);
INSERT INTO dbo.SampleTable([System],OrderNo)
VALUES('system1',1),
('system2',2),
('system3',3),
('system4',4),
('system1',1),
('system2',2),
('system5',1),
('system6',2),
('system7',1),
('system8',2);
GO
WITH Groups AS(
SELECT ID,
[System],
COUNT(CASE WHEN OrderNo = 1 THEN 1 END) OVER (ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
FROM dbo.SampleTable)
SELECT [System] AS Parent,
LEAD([System]) OVER (PARTITION BY Grp ORDER BY ID) AS Child
FROM Groups;
GO
如果无法访问 LEAD
和 ROWS BETWEEN
,您将必须更有创意;并且解决方案会慢得多:
WITH Groups AS(
SELECT ST.ID,
ST.[System],
G.Grp
FROM dbo.SampleTable ST
CROSS APPLY (SELECT COUNT(*) AS Grp
FROM dbo.SampleTable CA
WHERE CA.OrderNo =1
AND CA.ID <= ST.ID) G)
SELECT G1.[System] AS Parent,
G2.[System] AS Child
FROM Groups G1
LEFT JOIN Groups G2 ON G1.Grp = G2.Grp
AND G1.ID = G2.ID - 1;
我有一个 table 包含系统和订单号列,但不是 unique.I 我想根据订单号连接系统
+----------------------+
¦ system ¦OrderNo¦
¦--------------+-------+
¦ system1 ¦ 1 ¦
¦ system2 ¦ 2 ¦
¦ system3 ¦ 3 ¦
¦ system4 ¦ 4 ¦
¦ system1 ¦ 1 ¦
¦ system2 ¦ 2 ¦
¦ system5 ¦ 1 ¦
¦ system6 ¦ 2 ¦
¦ system7 ¦ 1 ¦
¦ system8 ¦ 2 ¦
+----------------------+
如何根据 OrderNo 列生成父子关系。其中1-2-3-4是一组,1-2,1-2,1-2是另一组
想要的输出如下
+----------------------+
¦ Parent ¦Child ¦
¦--------------+-------+
¦ system1 ¦system2¦
¦ system2 ¦system3¦
¦ system3 ¦system4¦
¦ system4 ¦NULL ¦
¦ system1 ¦system2¦
¦ system2 ¦NULL ¦
¦ system5 ¦system6¦
¦ system6 ¦NULL ¦
¦ system7 ¦system8¦
¦ system8 ¦NULL ¦
+----------------------+
正如我在评论中提到的,如果这些是您仅有的专栏,那么您所追求的是无法实现的。如果没有某种升序唯一键,您就无法确定这种关系。如果我们做添加一个唯一的升序键然后我们可以实现这个。
如果您使用的是 SQL Server 2012+(2008 不受支持,扩展支持即将结束,因此升级现在应该是一个非常高的优先级),那么您可以生成您的岛屿使用 ROWS BETWEEN
然后使用 LEAD
:
CREATE TABLE dbo.SampleTable (ID int IDENTITY(1,1),
[system] varchar(8),
OrderNo int);
INSERT INTO dbo.SampleTable([System],OrderNo)
VALUES('system1',1),
('system2',2),
('system3',3),
('system4',4),
('system1',1),
('system2',2),
('system5',1),
('system6',2),
('system7',1),
('system8',2);
GO
WITH Groups AS(
SELECT ID,
[System],
COUNT(CASE WHEN OrderNo = 1 THEN 1 END) OVER (ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
FROM dbo.SampleTable)
SELECT [System] AS Parent,
LEAD([System]) OVER (PARTITION BY Grp ORDER BY ID) AS Child
FROM Groups;
GO
如果无法访问 LEAD
和 ROWS BETWEEN
,您将必须更有创意;并且解决方案会慢得多:
WITH Groups AS(
SELECT ST.ID,
ST.[System],
G.Grp
FROM dbo.SampleTable ST
CROSS APPLY (SELECT COUNT(*) AS Grp
FROM dbo.SampleTable CA
WHERE CA.OrderNo =1
AND CA.ID <= ST.ID) G)
SELECT G1.[System] AS Parent,
G2.[System] AS Child
FROM Groups G1
LEFT JOIN Groups G2 ON G1.Grp = G2.Grp
AND G1.ID = G2.ID - 1;