SQL-按顺序选择父记录和子记录

时间:2018-06-21 18:30:52

标签: sql sql-server tsql join common-table-expression

我有一个表,在同一表中同时具有问题ID和父问题ID:

QUES_ID | Ques_Txt  | Parent_Ques_Id
--------+-----------+---------+---------------
     97  |  X       | NULL
     101 |  Y       | NULL
     115 |  Z       | NULL
     198 |  A       | 97
     302 |  B       | 97
     151 |  C       | 101
     91  |  D       | 115
   1110  |  E       | 115
   1111  |  F       | 115

现在,我想按以下顺序获取结果集:

QUES_ID | Ques_Txt  | Parent_Ques_Id
--------+-----------+---------+---------------
     97  |  X       | NULL
     198 |  A       | 97
     302 |  B       | 97
     101 |  Y       | NULL
     151 |  C       | 101
     115 |  Z       | NULL         
     91  |  D       | 115
   1110  |  E       | 115
   1111  |  F       | 115

我在子问题的上方列出了父问题,我已经研究了一个类似的查询,但是我发现的全部是如何使用左联接或CTE显示父子记录,而不是按照我要查找的顺序在上表中。谁能帮忙,我还在学习。

3 个答案:

答案 0 :(得分:4)

您可以使用coalesce的技巧来完成此操作:

select *
from t
order by coalesce(parent_ques_id, ques_id), parent_ques_id, ques_id

排序逻辑为:

  1. 将所有父子关系一个接一个地排序(97,101,115)coalesce(parent_ques_id, ques_id)-为父母分配一个自己的ID(而不是null)与他的孩子进行排序
  2. 使父级出现在每个组parent_ques_id上-默认情况下,空值在ASC顺序中的值之前排在前面(在SQL Server中)
  3. 按孩子的ID ques_id排序孩子

答案 1 :(得分:2)

使用order by子句:

order by (case when Parent_Ques_Id is null 
               then QUES_ID else Parent_Ques_Id end), Parent_Ques_Id, QUES_ID;

答案 2 :(得分:0)

好的,这是我的处理方式,此版本最多可处理99个兄弟姐妹。如我所说,这很复杂。

;WITH cte AS
(
    SELECT
        QUES_ID,
        Quest_Txt,
        Parent_Quest_Id,
        --(assumes max 9 siblings)
        RIGHT('0'+CAST(ROW_NUMBER()OVER(PARTITION BY Parent_Quest_Id ORDER BY Quest_Txt) AS VARCHAR(MAX)), 1) AS [path],
        0 AS level
    FROM Questions
    WHERE Parent_Quest_Id = 0

  UNION ALL
    SELECT
        t.QUES_ID,
        t.Quest_Txt,
        t.Parent_Quest_Id,
        [path] +'-'
        --(assumes max 99 siblings)
        + RIGHT('00'+CAST(ROW_NUMBER()OVER(PARTITION BY t.Parent_Quest_Id ORDER BY t.Quest_Txt) AS VARCHAR(max)), 2),
        level+1
    FROM cte
    JOIN Questions t ON cte.QUES_ID = t.Parent_Quest_Id
)
SELECT
    QUES_ID,
    Quest_Txt,
    Parent_Quest_Id,
    [path]
FROM cte
ORDER BY path