Order parent child records by parent group and children

一世执手 提交于 2019-12-01 19:28:57

问题


I need sort query results by specific two related columns. My table is:

Row no | Col 1 | Col 2 | Col 3 | Col 4
    1  |   1   |  X    |  1    |  5
    2  |   2   |  Y    |  1    |  6
    3  |   5   |  Z    |  2    |  7
    4  |   6   |  T    |  2    |  0
    5  |   7   |  T    |  3    |  0
    6  |   6   |  W    |  2    |  0

The values in Col 4 represents the child record linked to Col 1.

So for Row no = 1 the next child record is row 3, where Col 1 holds the value of Col 4 from the first row.

The next child row for row 3 is row 5, based on the link between Col 1 and Col 4.

And I'd like to return this results:

Row no | Col 1 | Col 2 | Col 3 | Col 4
    1  |   1   |  X    |  1    |  5
    3  |   5   |  Z    |  2    |  7
    5  |   7   |  T    |  3    |  0    
    2  |   2   |  Y    |  1    |  6
    4  |   6   |  T    |  2    |  0
    6  |   6   |  W    |  2    |  0 

So I want the ordering to show a Parent row, followed by it's child rows, before moving on to the next top level Parent row.


回答1:


You can achieve what you're after with a Recursive CTE to find all the parent records and link them to their child records.

Dummy table setup:

CREATE TABLE #Table1
    (
      [Row no] INT ,
      [Col 1] INT ,
      [Col 2] VARCHAR(1) ,
      [Col 3] INT ,
      [Col 4] INT
    );

INSERT  INTO #Table1
        ( [Row no], [Col 1], [Col 2], [Col 3], [Col 4] )
VALUES  ( 1, 1, 'X', 1, 5 ),
        ( 2, 2, 'Y', 1, 6 ),
        ( 3, 5, 'Z', 2, 7 ),
        ( 4, 6, 'T', 2, 0 ),
        ( 5, 7, 'T', 3, 0 ),
        ( 6, 6, 'W', 2, 0 );

Recursive CTE:

;WITH    cte
          AS ( SELECT   * ,
                        ROW_NUMBER() OVER ( ORDER BY t1.[Col 1] ) GroupNo
               FROM     #Table1 t1
               WHERE    t1.[Col 1] NOT IN ( SELECT  [Col 4] FROM #Table1 )
               UNION ALL
               SELECT   t.* ,
                        cte.GroupNo
               FROM     #Table1 t
                        INNER JOIN cte ON cte.[Col 4] = t.[Col 1]
             )
    SELECT  *
    FROM    cte
    ORDER BY cte.GroupNo , cte.[Row no]

DROP TABLE #Table1

This combines 2 queries with a UNION ALL. The first query finds the top level items where the value of [Col 1] does not appear in [Col 4]:

WHERE    t1.[Col 1] NOT IN ( SELECT  [Col 4] FROM #Table1 )

The second query finds the child records on the first query with this JOIN:

INNER JOIN cte ON cte.[Col 4] = t.[Col 1]

For the ordering, I've used the following to give the the results of the first query a GroupNo, which is used later to order the records:

ROW_NUMBER() OVER ( ORDER BY t1.[Col 1] ) GroupNo 


来源:https://stackoverflow.com/questions/29274590/order-parent-child-records-by-parent-group-and-children

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!