sql - 按显示顺序和父 ID 对列进行排序

标签 sql sql-order-by

我有一个数据集,其中有一个行列表,每行都有一个 ID、显示 order 和一个可为空的 parentID。我需要将它们按升序显示顺序返回,并分组在其父级后面(如果有的话)。我不知道该怎么做。我正在考虑尝试一些工会,但需要的工会数量是无限的。

ID  order   parentID
4   1   
6   2   
5   1       6
1   2       6
7   3       6
77  3   
89  1       77
43  4   
23  5   
2   1       23
3   2       23

最佳答案

您必须构建一个排序机制,以考虑级别之间的排序以及每个级别内的排序。我将向您展示如何使用递归 CTE 来完成此操作。

首先,您需要确定可以比较多少个元素。在您的表中,答案最多为 5,但这可以是任意的。所以我们首先查询它

declare @dyn_ord as int = (select len(MAX(ordering)) from #A)

这会获取位数,在本例中仅为 1。在这里,我使用“#A”作为表的名称。

接下来,我们使用我们想要的字段设置递归 CTE

declare @dyn_ord as int = (select len(MAX(ordering)) from #A)

; with
    Parent as (
    -- Anchor member definition
        select    a.Id -- of course show the ID
                , a.parentID -- show the parent's ID
                , cast(a.ID as varchar(max)) as Path -- this is bonus to help understand recursion
                , CAST((REPLACE(STR(ordering,@dyn_ord),' ','0')) AS nvarchar(max)) AS OrderString -- our modified ordering, explanation to follow
            from #A a
            where a.parentId is null
        union all
    -- Recursive member definition
        select    c.Id
                , c.parentID
                , cast(Path + ' -> ' + cast(c.ID as varchar(max)) as varchar(max)) as Path
                , (p.OrderString + '.' + CAST((REPLACE(STR(c.ordering,@dyn_ord),' ','0')) AS nvarchar(max))) AS OrderString
            from #A as c
            inner join Parent as p
                on c.parentID = p.ID
    )
SELECT    Id
        , parentID
        , Path
        , OrderString
    FROM Parent
    order by OrderString asc

OrderString 是我们用来订购的机制。在给定级别中,它 (1) 接受排序,(2) 将其转换为字符串,(3) 根据需要填充任何额外的零。如果您尝试比较 1 和 10 等顺序,则需要第三步,这并不总能在字符串比较中提供您想要的结果。

在递归步骤中,“OrderString”(1) 从父级获取已有的排序,(2) 附加一个句点(不需要,但有助于理解排序),(3) 然后执行相同的三个操作步骤如上一段。

关于sql - 按显示顺序和父 ID 对列进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42658599/

相关文章:

sql - 如何按另一个表列排序

mysql - SQL:查询给定日期的时间段

sql - FROM子句中出现Delphi语法错误,但是-没有FROM子句

sql - Adventure Work 数据库中复合主键的概念

mysql - 如何按多个时间戳字段排序并按时间顺序返回它们?

mysql - 查询获取 12 个月内 TOP 3 行

mysql - 求前两列的总和以及它们有多少分?

mysql - 如何在 SELECT 中使用 COUNT 别名?

PHP MySQL : COUNT/SUM a non integer column with different values

mysql - 显示 mysql 所有项目的 10%