Родительская дочерняя иерархия на основе неуникального номера заказа - PullRequest
0 голосов
/ 25 ноября 2018

У меня есть таблица, содержащая столбец системы и номера заказа, который не является уникальным. Я хотел бы подключить систему на основе номера заказа

+----------------------+  
¦ 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   ¦ 
+----------------------+

1 Ответ

0 голосов
/ 25 ноября 2018

Как я уже упоминал в своем комментарии, если это единственные столбцы, которые у вас есть, то, что вы ищете, не достижимо.Без какого-то восходящего уникального ключа у вас нет возможности определить отношения.Если мы делаем и добавляем уникальный восходящий ключ, тогда мы можем достичь этого.

Если вы использовали 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;
...