【问题标题】:Calculating Running Totals - TSQL?计算运行总计 - SQL?
【发布时间】:2023-03-23 11:31:01
【问题描述】:

我正在尝试计算一个时间段内的运行总计,每个时间段都会累积到下一个时间段以获得累积总计。

真实数据中会有多个事件以及多种事件类型和成本类型 - 但在下面的示例中,我只显示一种事件和一种类型。如果我能让它发挥作用,我也可以让它适用于其他类型。

下面的截图是我预期的输出:

我想将两种准备金的每个月的金额相加:费用和赔偿 - 所以第 1 个月的总金额为 31.7 万美元。第 2 个月的总额约为 4.1k 美元,因此这将添加到前几个月的总额中,给我 35.9k 美元。并且这个累计应该会一直持续到最后一条记录。

我正在尝试各种方法通过窗口函数求和,但到目前为止我无法获得预期的结果。关于如何达到这个总数的任何建议?

示例数据如下:

CREATE TABLE #temptable
( Catastrophe VARCHAR (60), Type VARCHAR (256), CostType VARCHAR (256), FirstLossDate DATE, MonthNumber INT, Amount DECIMAL (38, 6) );

INSERT INTO #temptable
( Catastrophe, Type, CostType, FirstLossDate, MonthNumber, Amount) 
VALUES
('Hurricane Humberto', 'Reserve', 'Expense - A&O', N'2007-09-13', 1, 13460.320000),
('Hurricane Humberto', 'Reserve', 'Indemnity', N'2007-09-13', 1, 18314.610000),
('Hurricane Humberto', 'Reserve', 'Expense - A&O', N'2007-09-13', 2, -1589.340000),
('Hurricane Humberto', 'Reserve', 'Indemnity', N'2007-09-13', 2, 5750.000000),
('Hurricane Humberto', 'Reserve', 'Expense - A&O', N'2007-09-13', 3, -2981.250000),
('Hurricane Humberto', 'Reserve', 'Indemnity', N'2007-09-13', 3, -10000.000000),
('Hurricane Humberto', 'Reserve', 'Expense - A&O', N'2007-09-13', 4, 0.000000),
('Hurricane Humberto', 'Reserve', 'Indemnity', N'2007-09-13', 4, 0.000000),
('Hurricane Humberto', 'Reserve', 'Expense - A&O', N'2007-09-13', 5, 0.000000),
('Hurricane Humberto', 'Reserve', 'Indemnity', N'2007-09-13', 5, 0.000000);

SELECT Catastrophe,
       Type,
       CostType,
       FirstLossDate,
       MonthNumber,
       Amount,
       SUM ( Amount ) OVER (PARTITION BY Catastrophe, MonthNumber, Type ORDER BY MonthNumber ROWS UNBOUNDED PRECEDING  ) AS RunningTotals,
       SUM ( Amount ) OVER (PARTITION BY Catastrophe, Type, MonthNumber) AS RunningTotal2
FROM #temptable
ORDER BY Catastrophe,
         Type,
         MonthNumber;

DROP TABLE #temptable;

【问题讨论】:

  • 我认为在定义分区窗口时需要使用 RANGE 而不是 ROWS。 ROWS 和 RANGE 处理关系的方式不同,ROWS 以任意顺序递增,RANGE 为范围内的所有行提供相同的值。
  • 不,SIA2 - RunningTotal2 不是我想要的。它每个月都会重置,不是累积的。

标签: sql tsql sql-server-2016


【解决方案1】:

试试这个:

SELECT Catastrophe,
       Type,
       CostType,
       FirstLossDate,
       MonthNumber,
       Amount,
       SUM(Amount) OVER (PARTITION BY Catastrophe, Type ORDER BY MonthNumber asc RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS RunningTotals
FROM 
       temptable
ORDER BY 
       Catastrophe,
       Type,
       MonthNumber;

我认为您的主要问题在于partition by 子句-它旨在“重置”计算-因此您可以计算许多组的窗口函数。

根据文档:

PARTITION BY 将查询结果集划分为分区。窗户 函数分别应用于每个分区和计算 为每个分区重新启动。

REF

SQL FIDDLE

【讨论】:

  • 将 ROWS 换成 RANGE 可以与预期的输出完全匹配。
  • 谢谢!我从来没有在之间使用过 RANGE 并且确实有效。需要进一步研究该功能。欣赏它。
  • 如果您需要更多细节,那么这可能是一个很好的起点:sqlperformance.com/2019/08/sql-performance/…
  • 在这里使用行和范围之间的区别在于,该范围还将考虑在有序字段(和分区)中具有相同元素的行,并且行将逐行(即之前的所有内容) + 当前,一旦我们订购它)。分区是第二个重要的事情 - 你不能按月分区,因为当你进入新月份时,这将始终“重置”计算。
猜你喜欢
  • 2010-10-26
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
相关资源
最近更新 更多