我有一张这样的表:
table item
(
id int,
quantity float,
father int, -- refer to item itself in case of subitem
)
我需要像这样总结数量和儿子的数量:
select i.id, max(i.quantity)+sum(ft.quantity) as quantity
from item i
left join item ft on ft.id=i.id
group by i.id
我的麻烦是因为父子之间的关系是递归的,所以我想总结他的祖父数量等...而且我不知道最大的深度,而不是我多次不能加入。
我该怎么办? 谢谢。
答案 0 :(得分:2)
您必须使用递归CTE。这样的事情: SQL Fiddle Demo
这会给你类似的东西:
;WITH FathersSonsTree
AS
(
SELECT Id, quantity, 0 AS Level
FROM Items WHERE fatherid IS NULL
UNION ALL
SELECT c.id, c.quantity, p.level+1
FROM FathersSonsTree p
INNER JOIN items c ON c.fatherid = p.id
), ItemsWithMaxQuantities
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY level
ORDER BY quantity DESC) rownum
FROM FathersSonsTree
)
SELECT
ID,
(SELECT MAX(Quantity)
FROM FathersSonsTree t3
WHERE t3.level = t1.level
) +
ISNULL((SELECT SUM(t2.Quantity)
FROM FathersSonsTree t2
WHERE t1.level - t2.level = 1), 0)
FROM FathersSonsTree t1
ORDER BY ID;
答案 1 :(得分:0)
您可以尝试构建一个递归CTE(公用表表达式),如本文关于SQLAuthority所述:
作者Pinal Dave讨论了在employees表上使用递归CTE,该表具有自引用ManagerID的外键,以返回员工列表,其中包含他们与层次结构顶部之间的层数。员工没有经理(ManagerID = NULL)。这不完全是你想要的,但它可能会让你开始。
我做了一些实验,最后得到了与Mahmoud Gamal的解决方案非常相似的东西,但略有不同,不仅包括父母,祖父母,曾祖父母等数量,还包括儿童数量。
这是我使用的测试表:
CREATE TABLE Items(ID int IDENTITY
CONSTRAINT PK_Items PRIMARY KEY,
Quantity int NOT NULL,
ParentID int NULL
CONSTRAINT FK_Item_Parents REFERENCES Items(ID));
数据:
ID Quantity ParentID ------------------------------------------------------------ 1 10 {NULL} 2 10 1 3 10 2 4 10 3 5 10 2
这是我的递归查询:
WITH cteRecursiveItems
AS (SELECT Id,
quantity,
0
AS Level
FROM Items
WHERE ParentID IS NULL
UNION ALL
SELECT i.id,
i.quantity,
cri.level + 1
FROM
cteRecursiveItems cri
INNER JOIN items i ON i.ParentID = cri.id)
SELECT ID,
Quantity + (
SELECT MAX(Quantity)
FROM cteRecursiveItems cri3
WHERE cri3.level = cri1.level) + (
SELECT SUM(cri2.Quantity)
FROM cteRecursiveItems cri2
WHERE cri1.level - cri2.level = 1) as Total
FROM cteRecursiveItems cri1
ORDER BY ID;
这是我在测试表上运行它得到的结果:
ID Total ---------------------------------------- 1 {NULL} 2 30 3 30 4 40 5 30
它仍然需要稍微调整一下,因为第一行和第二行都是10行。第1行应该总共有10行,第2行应该总共有20行。我正在做一个注释,试着解决这个问题。我回家(了。现在不能在我的雇主上花太多时间。 :)其他行具有我期望的值。