【问题标题】:sum with conditional grouping条件分组求和
【发布时间】:2023-03-20 12:06:02
【问题描述】:

我有 2 个表:部门和销售。在我的部门表中,我有一个劳动部门 ID 和与之关联的销售部门的 ID。我还想让一个部门的销售额“汇总”到另一个部门。我需要查询帮助以“汇总”销售额。

这是表格:

TABLE = Departments
LaborDeptid | AssociatedSalesDept | RollUpTo
1                    101              0   
2                    102              0
3                    103              1
4                    104              0

TABLE = Sales
Date      | Sales | SalesDept
1/1/2014    10.00     101 
1/1/2014    10.00     101
1/1/2014    10.00     102
1/1/2014    10.00     102
1/1/2014    10.00     103
1/1/2014    10.00     103
1/1/2014    10.00     104
1/1/2014    10.00     104

这是我想要的输出:

OUTPUT
Date      | LaborDept | TotalSales
1/1/2014       1         40.00
1/1/2014       2         20.00
1/1/2014       4         20.00

如您所见,劳动部门 1 包括销售部门 101 和 103 的销售。不过,我不知道该怎么做。按部门按天汇总的查询很简单:

select 
    Date,
    LaborDept,
    sum(sales) as TotalSales
from sales s
inner join departments d on s.SalesDept = d.AssociatedSalesDept 
group by Date,LaborDept`

但我将如何进行“汇总”?我尝试在 join 中添加一个 case 语句,如下所示:

select 
    sum(sales) as TotalSales,
    Date,
    LaborDept
from sales s
inner join departments d on s.SalesDept = case when d.RollUpTo <> 0 then 
(select AssociatedSalesDept 
from departments
where d.RollUpTo = LaborDeptID)
else d.AssociatedSalesDept end
group by Date,LaborDept

但这只是将 103 销售部门全部删除。而且这似乎不是正确的方法。

【问题讨论】:

  • 非常感谢所有 3 个答案。我喜欢概念上的 cte 方法,但它对我不起作用(我想可能是我做错了)。最后,DavidN 的解决方案很容易理解,并且在大约 20K 行数据上表现良好。谢谢。

标签: sql sql-server group-by sql-server-2008-r2 sum


【解决方案1】:
select s.[Date], coalesce(d2.LaborDeptid,d1.LaborDeptid) [LaborDept], sum(s.Sales) [TotalSales]
from Sales s
join Departments d1 on s.SalesDept = d1.AssociatedSalesDept
left join Departments d2 on d1.RollUpTo = d2.LaborDeptid
group by s.[Date], coalesce(d2.LaborDeptid,d1.LaborDeptid)

【讨论】:

    【解决方案2】:

    我不得不考虑一下,但这里有一个解决方案:

    WITH cte AS (
    SELECT CASE WHEN RollUpTo = 0 THEN LaborDeptId ELSE RollUpTo END AS LaborDeptId, AssociatedSalesDept
    FROM departments)
    
    SELECT s.date, d.LaborDeptid, SUM(s.Sales) AS TotalSales
    FROM Sales s 
    INNER JOIN cte d ON s.SalesDept = d.AssociatedSalesDept
    GROUP BY s.date, d.LaborDeptid
    

    【讨论】:

    • 在我的测试中,这个比 DavidN 的要好一点,因为它对每个表只读取一次,而不是读取部门表两次。
    【解决方案3】:
        SELECT s.Date, 
               d.LaborDeptId,
               SUM(Sales) + ISNULL((SELECT 
                                CASE Departments.RollUpTo
                                    WHEN 0 THEN SUM(0)
                                    ELSE SUM(Sales)
                                END
                              FROM Departments
                        INNER JOIN Sales ON Departments.AssociatedSalesDept = Sales.SalesDept
                             WHERE Departments.RollUpTo = d.LaborDeptId
                               AND Departments.RollUpTo <> 0
                          GROUP BY Departments.RollUpTo), 0) AS TotalSales
          FROM Departments d 
    INNER JOIN Sales s ON d.AssociatedSalesDept = s.SalesDept
         WHERE d.RollUpTo = 0
      GROUP BY s.Date, d.LaborDeptId, d.RollUpTo;
    

    使用子查询的另一个选项。不过我更喜欢 DavidN。

    【讨论】:

      猜你喜欢
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多