【问题标题】:How to get running total for each quarter and instead of duplicate value to have 0. Using SQL Server 2012如何获得每个季度的运行总计,而不是重复值为 0。使用 SQL Server 2012
【发布时间】:2019-01-09 14:40:37
【问题描述】:

我需要计算每个季度的总保费。但是我的数据是按日期细分的。

所以我需要基于年份和季度的第一行显示值,但是如果后面的行具有相同的YearQuarter,那么值应该是 0。

这就是现在的样子:

但我需要这样:

使用虚拟数据查询:

declare @TempTable1 table (ID int, Date date, PolicyNumber varchar(100), Premium money)

insert into @TempTable1 
values (1, '2018-01-01', 'Policy1', 100),
       (2, '2018-02-08', 'Policy2', 200),
       (3, '2018-04-15', 'Policy3', 300),
       (4, '2018-05-31', 'Policy4', 150),
       (5, '2018-07-10', 'Policy5', 250),
       (6, '2018-11-23', 'Policy6', 350),
       (7, '2018-12-05', 'Policy7', 330),
       (8, '2019-01-09', 'Policy8', 140),
       (9, '2019-06-18', 'Policy9', 225),
       (10, '2019-06-28', 'Policy10', 145)

SELECT  
    ID, 
    Date, 
    PolicyNumber,    
    YEAR(date) AS Year, 
    DATEPART(qq, date) AS Quarter,
    Premium,
    SUM(premium) OVER (ORDER BY YEAR(date), DATEPART(qq, date)) AS RunningTotal
FROM
    @TempTable1

是否有可能在同一个SELECT 语句中实现这一点?

谢谢

【问题讨论】:

    标签: sql-server tsql sql-server-2012


    【解决方案1】:

    试试这个。它为每个年份和季度分区创建一个 row_number,并且只允许 row = 1 的计算值

    SELECT ID,
            Date,
            policynumber, 
            dq2.year,
            dq2.Quarter,
            premium,
            case when rn=1 then runningtotal else 0 end 'runningtotal' 
    from
        (
            select *,row_number() OVER (partition by year,quarter order by policynumber) as RN FROM
            (
            select  ID, 
                    Date, 
                    PolicyNumber,    
                    Year(date) as 'Year', 
                    DATEPART(qq,date) as [Quarter],
                    Premium,
                    sum(premium) over (order by Year(date),DATEPART(qq,date)) as RunningTotal
    
            from @TempTable1
            ) DQ
        ) DQ2
    

    【讨论】:

      【解决方案2】:

      您需要做的就是通过lag() 窗口函数添加检查Year/Quarter 是否正在更改。

      select  ID, 
              Date, 
              PolicyNumber,    
              Year(date) as Year, 
              DATEPART(qq,date) as Quarter,
              Premium,
              case when lag(DATEPART(qq,date), 1, null) over (order by Year(date),DATEPART(qq,date)) - DATEPART(qq,date) = 0 then 0 else
              sum(premium) over (order by Year(date),DATEPART(qq,date)) end as RunningTotal
      from @TempTable1
      

      我建议将初始计算列包装在子查询中,以减少所涉及的 datepart() 计算的数量,但任一解决方案都可以。

      子查询选项:

      select a.ID
      , a.Date
      , a.PolicyNumber
      , a.Year
      , a.Quarter
      , a.Premium
      , case when lag(a.Quarter, 1, null) over (order by a.Year,a.Quarter) - a.Quarter = 0 then 0 else
                  sum(a.premium) over (order by a.Year,a.Quarter) end as RunningTotal
      from (
          select  ID, 
                  Date, 
                  PolicyNumber,    
                  Year(date) as Year, 
                  DATEPART(qq,date) as Quarter,
                  Premium
          from @TempTable1
          ) as a
      

      【讨论】:

      • 谢谢!有什么方法可以稍微调整一下这个查询并在不运行 Total 且不分组的情况下只获得 SUM 吗?谢谢
      • @Oleg 您介意用第二个所需的输出更新您的问题吗?我认为这将帮助我准确了解您要查找的内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多