CTE是否用于计算辅助表中引用的树ID

问题描述 投票:2回答:2

我有一个简单的树表,其中引用了简单清单应用程序的类型,子类型(无级别限制),品牌和模型。

数据结构如下所示:(nodeIsModel是一个布尔字段,用于计算)

ID    parentID    label               nodeIsModel
 1     -1          Root                   0  
 2     1           IT                     0
 3     2           Desktops               0
 4     3           Hewlett-Packard        0 
 5     4           HP Z240                1
 6     4           H97M-PLUS              1
 7     2           Laptops                0
 8     7           DELL                   0
 9     8           G3 3579                1

依此类推。

此表(显示在Delphi下的DBTreeView中)给了我类似的东西:

ID     Label
1      Root
2        |_IT
3        |__Desktops
4        |___Hewlett-Packard
5        |____HP Z240
6        |____H97M-PLUS
7        |__Laptops
8        |___DELL
9        |____G3 3579

此表是参考表,用户将在其中选择并将一组类型,子类型,品牌和型号分配给设备。

设备被保存在另一个表(data_items)中,并通过所选模型的ID(最低树结构级别)链接到上一个表。

例如,我的台式机将另存为:

itemID    itemLabel         typeID
  1       RSI-HP-DESK-01      5

因为它是HP Z240工作站,在树表中被称为ID 5。

从此typeID开始,我有一个CTE查询,它会爬到树上以从子ID查找所有父代,这没问题。

我的问题如下:

我希望在显示DBTreeView时显示一列:

  • 所有型号的项目数

也是

  • 每个品牌的型号的总和(计算型号)
  • 每个子类型的模型的总和
  • 每种类型的模型的总和...

依此类推...

例如,如果我们在数据库中有2台HP Z240工作站和1台DELL G3笔记本电脑,则TreeView看起来像:

ID     Label                    NB
1      Root
2        |_IT                   3
3        |__Desktops            2
4        |___Hewlett-Packard    2
5        |____HP Z240           1
6        |____H97M-PLUS         1
7        |__Laptops             1
8        |___DELL               1
9        |____G3 3579           1

基于树表中的“ nodeIsModel”布尔字段,我尝试了查询,有些使用了CTE,有些则没有,但是我对JOIN和子查询感到困惑,并且还收到有关以下内容的错误消息:

CTE中不允许汇总查询

任何建议都将不胜感激。


根据Dale K的要求,这是递归查询,从我的孩子ID开始给我所有父母:

此查询有效。我正在寻找一个新的查询,该查询将树表与项目表结合在一起,从而对在树的每个级别上分配给项目的模型进行计数

WITH CTE AS (
SELECT
    ID,
    parentID,
    label,
    CAST (nodeLevel AS INTEGER) AS LEVEL
FROM
    dico_TBM
WHERE
    ID = :lookupID
UNION ALL
    SELECT
        r.ID,
        t.parentID,
        t.label,
        LEVEL - 1
    FROM
        dico_TBM t
    INNER JOIN CTE r ON t.ID = r.parentID
) SELECT DISTINCT
    r.ID,
    r.parentID,
    r.label,
    LEVEL
FROM
    CTE r
WHERE
    LEVEL > 0
ORDER BY
    LEVEL

(nodeLevel是一个整数,给出了我在问题中没有提到的树中节点的级别,认为它没有意义,而:lookupID是我作为参数传递给查询的起始子节点的ID。 )

sql sql-server hierarchy hierarchical-data
2个回答
0
投票

这里是一种可以帮助您解决问题的方法。以下是我的类似设置enter image description here

下面的查询为我们提供了资源树中每个级别的资源计数。

;with CTE1 AS (
  SELECT r.id, r.label, r.parentID, count(*) AS ItemCount 
    FROM resourcetree r 
    JOIN items i ON (r.id = i.resourceID) 
   GROUP BY r.id, r.label, r.parentID
), 
CTE2 AS (
  SELECT r.id, r.label, r.parentID, SUM(cte1.itemCount) AS ItemCount, 0 AS sumFlag 
    FROM resourceTree r 
    JOIN CTE1 ON (r.id = cte1.parentID) 
   GROUP BY r.id, r.label, r.parentID
  UNION ALL
  SELECT r.id, r.label, r.parentID, cte2.ItemCount AS ItemCount, 1 AS sumFlag 
    FROM resourceTree r 
    JOIN cte2 ON (r.id = cte2.parentID)
)
SELECT r.id, 
       r.label, 
       COALESCE(c2_1.ItemCount, c2_0.ItemCount, cte1.ItemCount, 0) AS ItemCount 
  FROM resourceTree r 
  LEFT JOIN cte1 ON r.id = cte1.id 
  LEFT JOIN cte2 c2_0 ON (r.id = c2_0.id AND c2_0.sumFlag = 0)
  LEFT JOIN (SELECT id, label, SUM(ItemCount) AS ItemCount 
               FROM CTE2 
              WHERE sumFlag = 1 
              GROUP BY id, label) c2_1 ON r.id = c2_1.id

下面是我得到的结果。希望能帮助到你。谢谢。

enter image description here

PS:我不必使用'NodeIsModel'标志


0
投票

使用nodeIsModel = 1作为recursive cte的锚点成员,然后从那里开始并上一层楼

with
rcte as
(
    select  *
    from    dico_TBM
    where   nodeIsModel = 1

    union all

    select  d.*
    from    rcte r
            inner join dico_TBM d   on  r.parnetID  = d.ID
)
select  ID, label, count(*) as NB
from    rcte
group by ID, label
order by ID
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.