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

统计分层SQL数据中的子级数

  •  20
  • Dennis G  · 技术社区  · 15 年前

    对于这样的简单数据结构:

    ID    parentID    Text        Price
    1                 Root
    2     1           Flowers
    3     1           Electro
    4     2           Rose        10
    5     2           Violet      5
    6     4           Red Rose    12
    7     3           Television  100
    8     3           Radio       70
    9     8           Webradio    90
    

    作为参考,层次结构树如下所示:

    ID    Text        Price
    1     Root
    |2    Flowers
    |-4   Rose        10
    | |-6 Red Rose    12
    |-5   Violet      5
    |3    Electro
    |-7   Television  100
    |-8   Radio       70
      |-9 Webradio    90
    

    我想计算每个级别的孩子数。所以我会得到一个新的专栏“noofchildren”,就像这样:

    ID    parentID    Text        Price  NoOfChildren
    1                 Root               8
    2     1           Flowers            3
    3     1           Electro            3
    4     2           Rose        10     1
    5     2           Violet      5      0
    6     4           Red Rose    12     0
    7     3           Television  100    0
    8     3           Radio       70     1
    9     8           Webradio    90     0
    

    我读了一些关于层次数据的东西,但是不知怎么的,我被parentid上的多个内部连接卡住了。也许有人能帮我。

    2 回复  |  直到 12 年前
        1
  •  24
  •   Lieven Keersmaekers    15 年前

    使用 CTE 会得到你想要的。

    • 递归地遍历所有子对象,记住根。
    • COUNT 每个根的项。
    • JOIN 这些再和你原来的表一起产生结果。

    测试数据

    DECLARE @Data TABLE (
      ID INTEGER PRIMARY KEY
      , ParentID INTEGER
      , Text VARCHAR(32)
      , Price INTEGER
    )
    
    INSERT INTO @Data
      SELECT 1, Null, 'Root', NULL
      UNION ALL SELECT 2, 1, 'Flowers', NULL
      UNION ALL SELECT 3, 1, 'Electro', NULL
      UNION ALL SELECT 4, 2, 'Rose', 10
      UNION ALL SELECT 5, 2, 'Violet', 5
      UNION ALL SELECT 6, 4, 'Red Rose', 12
      UNION ALL SELECT 7, 3, 'Television', 100
      UNION ALL SELECT 8, 3, 'Radio', 70
      UNION ALL SELECT 9, 8, 'Webradio', 90
    

    SQL语句

    ;WITH ChildrenCTE AS (
      SELECT  RootID = ID, ID
      FROM    @Data
      UNION ALL
      SELECT  cte.RootID, d.ID
      FROM    ChildrenCTE cte
              INNER JOIN @Data d ON d.ParentID = cte.ID
    )
    SELECT  d.ID, d.ParentID, d.Text, d.Price, cnt.Children
    FROM    @Data d
            INNER JOIN (
              SELECT  ID = RootID, Children = COUNT(*) - 1
              FROM    ChildrenCTE
              GROUP BY RootID
            ) cnt ON cnt.ID = d.ID
    
        2
  •  5
  •   mxsscott    12 年前

    考虑使用一种改进的预序树遍历方式来存储分层数据。见 http://www.sitepoint.com/hierarchical-data-database/

    然后,确定任何节点的子节点数变得很简单:

    SELECT (right-left-1) / 2 AS num_children FROM ...