代码之家  ›  专栏  ›  技术社区  ›  Nuno G

如何在SQL中对链接列表进行排序?

  •  15
  • Nuno G  · 技术社区  · 17 年前

    我已将链接列表实现为自引用数据库表:

    CREATE TABLE LinkedList(
        Id bigint NOT NULL,
        ParentId bigint NULL,
        SomeData nvarchar(50) NOT NULL) 
    

    其中id是主键,parentid是列表中上一个节点的id。第一个节点的parentID为空。

    现在,我想从表中进行选择,按照显示的顺序对行进行排序,作为列表中的节点。

    例如:如果表中包含行

    Id      ParentId  SomeData
    24971   NULL      0
    38324   24971     1
    60088   60089     3
    60089   38324     2
    61039   61497     5
    61497   60088     4
    109397  109831    7
    109831  61039     6
    

    然后,使用标准对其进行排序,应该会导致:

    Id      ParentId  SomeData
    24971   NULL      0
    38324   24971     1
    60089   38324     2
    60088   60089     3
    61497   60088     4
    61039   61497     5
    109831  61039     6
    109397  109831    7
    

    你应该使用 索美达塔 作为控制,所以请不要欺骗 按somedata排序 -)

    3 回复  |  直到 17 年前
        1
  •  9
  •   Quassnoi    17 年前

    在Oracle中:

    SELECT Id, ParentId, SomeData
    FROM (
      SELECT ll.*, level AS lvl
      FROM LinkedList ll
      START WITH
        ParentID IS NULL
      CONNECT BY
        ParentId = PRIOR Id
    )
    ORDER BY
      lvl
    

    另外,这是一个坏习惯 NULL 作为 ParentID ,因为它不能按索引搜索。插入ID为的代理根 0 -1 相反,使用 START WITH ParentID = 0 .

        2
  •  10
  •   Nuno G    17 年前

    我找到了一个sqlserver的解决方案,但是看起来比quassnoi的要大得多,也不那么优雅。

    WITH SortedList (Id, ParentId, SomeData, Level)
    AS
    (
      SELECT Id, ParentId, SomeData, 0 as Level
        FROM LinkedList
       WHERE ParentId IS NULL
      UNION ALL
      SELECT ll.Id, ll.ParentId, ll.SomeData, Level+1 as Level
        FROM LinkedList ll
       INNER JOIN SortedList as s
          ON ll.ParentId = s.Id
    )
    
    SELECT Id, ParentId, SomeData
      FROM SortedList
     ORDER BY Level
    
        3
  •  5
  •   Marc Gravell    17 年前

    (编辑:哦!我调试的时候,你也发现了!)

    在SQLServer中:

    ;WITH cte (Id, ParentId, SomeData, [Level]) AS (
        SELECT Id, ParentId, SomeData, 0
        FROM LinkedList
        WHERE ParentId IS NULL
        UNION ALL
        SELECT ll.Id, ll.ParentId, ll.SomeData, cte.[Level] + 1
        FROM LinkedList ll
        INNER JOIN cte ON ll.ParentID = cte.ID
    )
    SELECT * FROM cte
    ORDER BY [Level]