1

我有一张这样的桌子:

table item
(
   id    int,
   quantity float,
   father int, -- refer to item itself in case of subitem
)

我需要像这样总结 al 数量加上儿子数量:

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

我的麻烦是因为父子之间的关系是递归的,所以我想把他的祖父数量等相加……我不知道最大深度,比我不能加入很多次。

我能做些什么?谢谢你。

4

2 回答 2

2

您必须使用递归 CTE。像这样的东西:

;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;

SQL 小提琴演示

这会给你类似的东西:

| ID | QUANTITY |
-----------------
|  1 |       10 |
|  2 |       20 |
|  3 |       20 |
|  4 |       20 |
|  5 |       32 |
|  6 |       32 |
|  7 |       32 |
|  8 |       32 |
于 2012-12-11T16:01:25.703 回答
0

您可以尝试构建递归 CTE(公用表表达式),如 SQLAuthority 上的这篇文章中所述:

http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/

作者 Pinal Dave 讨论了在员工表上使用递归 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 数量 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;

这是我对测试表运行它得到的结果:

身份证总数             
--------------------------------------
1 {NULL}
2 30
3 30
4 40
5 30

它仍然需要稍微调整,因为第一行和第二行相差 10。第 1 行应该总共有 10,第 2 行应该总共有 20。我正在做笔记,以便在我回家时尝试修复它. 现在不能把我雇主的太多时间花在这上面。:) 其他行具有我期望的值。

于 2012-12-11T16:38:52.777 回答