CTE 或不用于计算二级 table 中引用的树 ID
CTE or not for counting tree id's referenced in secondary table
我有一个简单的树 table,我在其中引用了类型、sub-types(无级别限制)、品牌和模型以用于简单的库存应用程序。
数据结构如下图:(nodeIsModel为boolean字段,用于计算)
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
等等。
这个 table(显示在 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
这个table是参考table,用户可以在其中挑选和分配一个设备,一组类型,sub-types,品牌和型号。
装备保存在另一个table(data_items),并通过所选型号的id(树结构的最低层)链接到之前的table。
例如,我的台式电脑将保存为:
itemID itemLabel typeID
1 RSI-HP-DESK-01 5
因为它是 HP Z240 工作站并且在树 table 中被引用为 ID 5。
从这个 typeID 开始,我有一个 CTE 查询,它爬上树从 child ID 中找到所有 parents,这没问题。
我的问题如下:
我希望在显示 DBTreeView 时有一列显示:
- 所有模型的项目数
还有
- 每个品牌的型号总和(算上型号)
- 每个sub-types
模型的总和
- 每种类型 模型 的总和...
等等...
例如,如果我们在数据库中有 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
基于树 table 中的 "nodeIsModel" 布尔字段,我尝试了查询,有些查询带有 CTE,有些则没有,但我对 JOIN 和 sub-queries 感到困惑,还收到有关以下内容的错误消息:
aggregate queries not being allowed in CTE
如有任何建议,我们将不胜感激。
根据 Dale K 的要求,这里是递归查询,从 child ID 开始给我所有 parents :
这个查询有效。我正在寻找一个新查询,该查询将加入树 table 和项目 table,给出分配给树每个级别项目的模型计数
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 是起始 child 节点的 ID I作为参数传递给我的查询)
使用 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
下面是一种可以帮助您解决问题的方法。以下是我的类似设置
下面的查询为我们提供了资源树中每个级别的资源计数。
;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
下面是我得到的结果。希望能帮助到你。
谢谢
PS:我不必使用 'NodeIsModel' 标志
我有一个简单的树 table,我在其中引用了类型、sub-types(无级别限制)、品牌和模型以用于简单的库存应用程序。
数据结构如下图:(nodeIsModel为boolean字段,用于计算)
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
等等。
这个 table(显示在 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
这个table是参考table,用户可以在其中挑选和分配一个设备,一组类型,sub-types,品牌和型号。
装备保存在另一个table(data_items),并通过所选型号的id(树结构的最低层)链接到之前的table。
例如,我的台式电脑将保存为:
itemID itemLabel typeID
1 RSI-HP-DESK-01 5
因为它是 HP Z240 工作站并且在树 table 中被引用为 ID 5。
从这个 typeID 开始,我有一个 CTE 查询,它爬上树从 child ID 中找到所有 parents,这没问题。
我的问题如下:
我希望在显示 DBTreeView 时有一列显示:
- 所有模型的项目数
还有
- 每个品牌的型号总和(算上型号)
- 每个sub-types 模型的总和
- 每种类型 模型 的总和...
等等...
例如,如果我们在数据库中有 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
基于树 table 中的 "nodeIsModel" 布尔字段,我尝试了查询,有些查询带有 CTE,有些则没有,但我对 JOIN 和 sub-queries 感到困惑,还收到有关以下内容的错误消息:
aggregate queries not being allowed in CTE
如有任何建议,我们将不胜感激。
根据 Dale K 的要求,这里是递归查询,从 child ID 开始给我所有 parents :
这个查询有效。我正在寻找一个新查询,该查询将加入树 table 和项目 table,给出分配给树每个级别项目的模型计数
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 是起始 child 节点的 ID I作为参数传递给我的查询)
使用 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
下面是一种可以帮助您解决问题的方法。以下是我的类似设置
下面的查询为我们提供了资源树中每个级别的资源计数。
;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
下面是我得到的结果。希望能帮助到你。 谢谢
PS:我不必使用 'NodeIsModel' 标志