基于非唯一订单号的父子层次结构

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

如果无法访问 LEADROWS 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;