查询父类别

时间:2016-03-17 19:28:28

标签: sql sql-server sql-server-2008 sum

我现在有以下查询:

 SELECT DISTINCT c.Name as CategoryName, SUM(Amount) OVER(partition by c.Name order by c.Name) as Total
    FROM Statements s
    LEFT JOIN Categories c on c.Id = s.CategoryId
    WHERE Date >= '2016-01-01'
    ORDER BY c.Name

它到目前为止工作并获得每个类别的总量,但我需要的是以下内容。

类别可以包含子类别。我希望得到每一个根类别及其每一行的所有子类别的总和。

表示类别A有子项B和C.我想得到Statements中具有A,B或C类别的所有条目的总和。

类别表包含以下列:Id, Name, ParentId

声明表由以下coluimns组成:Id, Date, Amount, CategoryId

表类别的示例数据:

Id, Name, ParentId
1, A, null,
2, B, 1
3, C, 2
4, D, null

表格声明的示例数据

Id, Date, Amount, CategoryId
1, 2016-01-01, 100, 1
2, 2016-01-01, 200, 2
3, 2016-01-01, 800, 4
4, 2016-01-01, 300, 3

查询的输出应如下所示:

CategoryName, Total
A, 600
D, 800

理想情况下,我可以将parentCategoryId传递给我的样本null中的where子句,但也可以是2。

任何提示赞赏:)

2 个答案:

答案 0 :(得分:2)

一种常见的方法是使用递归CTE来构建层次结构。

;
WITH cte
AS (
    SELECT  [Id],
            [Name],
            [ParentId],
            [Name] AS [Root]
    FROM    Categories
    WHERE   ParentId IS NULL
    UNION ALL
    SELECT  c.[Id],
            c.[Name],
            c.[ParentId],
            [Root]
    FROM    Categories c
            JOIN cte ON c.ParentID = cte.Name
    )
SELECT  cte.[Root] AS [CategoryName],
        SUM(Amount) AS [Total]
FROM    cte
JOIN    Statements s ON s.CategoryId = cte.Id
GROUP BY cte.[Root]

答案 1 :(得分:1)

这不是问题的答案(在我写这篇文章时,缺乏关于如何在数据中描述父/子关系的充分信息)。但是,查询对于OP的既定目的而言并不是正确的查询。正确的查询是一个简单的聚合:

SELECT c.Name as CategoryName, SUM(Amount) as Total
FROM Table s LEFT JOIN
     Categories c 
     on c.Id = s.CategoryId
WHERE Date >= '2016-01-01'
GROUP BY c.Name
ORDER BY c.Name;

如果问题中的查询实际产生了有用的结果,给定每个类别的重复行,我会感到非常惊讶。