sql-server - SQL Server 列的层次总和

标签 sql-server hierarchical-data recursive-query

我按照图表设计了数据库。

enter image description here

  • Category表是自引用父子关系
  • 预算将包含为每个类别定义的所有类别和金额
  • Expense 表将包含已支出金额的类别条目(请考虑此表中的Total 列)。

我想编写选择语句来检索具有下面给出的列的数据集:

ID   
CategoryID   
CategoryName   
TotalAmount (Sum of Amount Column of all children hierarchy From BudgetTable  )   
SumOfExpense (Sum of Total Column of Expense  all children hierarchy from expense table)

我尝试使用 CTE,但无法产生任何有用的结果。提前感谢您的帮助。 :)

更新

我只是为了组合和简化数据,我使用下面的查询创建了一个 View 。

SELECT        
    dbo.Budget.Id, dbo.Budget.ProjectId, dbo.Budget.CategoryId, 
    dbo.Budget.Amount, 
    dbo.Category.ParentID, dbo.Category.Name, 
    ISNULL(dbo.Expense.Total, 0) AS CostToDate
FROM
    dbo.Budget 
INNER JOIN
    dbo.Category ON dbo.Budget.CategoryId = dbo.Category.Id 
LEFT OUTER JOIN
    dbo.Expense ON dbo.Category.Id = dbo.Expense.CategoryId

基本上应该产生这样的结果。

enter image description here

最佳答案

这是一个有趣的问题。我将用 Hierarchyid 来解决它。首先,设置:

USE tempdb;
IF OBJECT_ID('dbo.Hierarchy') IS NOT NULL
    DROP TABLE dbo.[Hierarchy];

CREATE TABLE dbo.Hierarchy 
(
    ID INT NOT NULL PRIMARY KEY,
    ParentID INT NULL,
        CONSTRAINT [FK_parent] FOREIGN KEY ([ParentID]) REFERENCES dbo.Hierarchy([ID]),
    hid HIERARCHYID,
    Amount INT NOT null
);

INSERT INTO [dbo].[Hierarchy]
        ( [ID], [ParentID], [Amount] )
VALUES  
    (1, NULL, 100 ),
    (2, 1, 50),
    (3, 1, 50),
    (4, 2, 58),
    (5, 2, 7),
    (6, 3, 10),
    (7, 3, 20)
SELECT * FROM dbo.[Hierarchy] AS [h];

接下来,使用 hiearchyid 的正确值更新 hid 列。我将为此使用沼泽标准递归 cte

WITH cte AS (
    SELECT  [h].[ID] ,
            [h].[ParentID] ,
            CAST('/' + CAST(h.[ID] AS VARCHAR(10)) + '/' AS VARCHAR(MAX)) AS [h],
            [h].[hid]
    FROM    [dbo].[Hierarchy] AS [h]
    WHERE   [h].[ParentID] IS NULL

    UNION ALL

    SELECT  [h].[ID] ,
            [h].[ParentID] ,
            CAST([c].[h] + CAST(h.[ID] AS VARCHAR(10)) + '/' AS VARCHAR(MAX)) AS [h],
            [h].[hid]
    FROM    [dbo].[Hierarchy] AS [h]
    JOIN    [cte] AS [c]
            ON [h].[ParentID] = [c].[ID]
)
UPDATE [h]
SET hid = [cte].[h]
FROM cte
JOIN dbo.[Hierarchy] AS [h]
    ON [h].[ID] = [cte].[ID];

现在繁重的工作已经完成,您想要的结果几乎已经轻松获得:

SELECT p.id, SUM([c].[Amount])
FROM dbo.[Hierarchy] AS [p]
JOIN [dbo].[Hierarchy] AS [c]
    ON c.[hid].IsDescendantOf(p.[hid]) = 1
GROUP BY [p].[ID];

关于sql-server - SQL Server 列的层次总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34626407/

相关文章:

c# - 如何仅显示最多 2 位小数的值

c# - 子集和问题

sql - 将数据类型 varchar 转换为 float isnumeric = 1 时出错

c# - 无法从配置值打开数据库连接

php - 我如何在 MySQL 中组织单个表中的分层数据组?

Azure 数据工厂 - 将 FTP 递归复制到数据库

php - 什么是用于保存具有共享子类别的分层标签云/类别的正确 SQL(MySQL) 数据结构?

windows - 可以在 Win32 中创建私有(private)注册表吗?

mysql - 变量重叠的递归 MySQL 查询

sql - 递归 CTE (T-SQL) 返回意外结果