计算分层SQL数据中的子项数

Den*_*s G 21 sql sql-server hierarchy hierarchical-data

对于简单的数据结构,例如:

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

我想计算每个级别的孩子数量.所以我会得到一个新的专栏"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
Run Code Online (Sandbox Code Playgroud)

我读了一些关于分层数据的事情,但我不知何故被困在parentID上的多个内连接上.也许有人可以帮助我.

Lie*_*ers 25

使用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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • @moontear:定义`CTE`的`WITH`子句可以与定义表提示的`WITH`子句混合.如果前者不是批处理中的第一个语句,则应使用分号明确分隔前者. (3认同)

小智 5

考虑使用修改的预订树遍历方式来存储分层数据.请访问http://www.sitepoint.com/hierarchical-data-database/

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

SELECT (right-left-1) / 2 AS num_children FROM ...
Run Code Online (Sandbox Code Playgroud)