SQL Server:N个月内计算行的总和

时间:2016-12-27 18:46:47

标签: sql-server

我是SQL Server的新手,并且有一个关于使用条件语句对计算行求和的问题。

我的数据组织如下:

ID  S_DATE     END_DATE   MNum  CHG  DateCHG
---------------------------------------------
1   1/26/2001   2/26/2001   7   NULL   1
1   2/27/2001   3/27/2001   8   1      1
1   3/28/2001   1/9/2003    9   1      21
1   1/10/2003   3/2/2004    11  2      14
1   3/3/2004    10/14/2004  10  -1     7
1   10/15/2004  6/22/2005   9   -1     8
1   6/23/2005   3/9/2008    8   -1    33
1   3/10/2008   1899-12-30  0   NULL    -1299
2   9/23/1993   9/11/2000   3   NULL    84
2   1/1/1999    12/31/1998  3   0   -1
2   9/12/2000   11/13/2001  2   -1  14
2   11/14/2001  1899-12-30  0   NULL    -1223

DateCHG等于S_DATE和S之间的月数。结束日期。我希望在上一个日期的3个月内发现CHG的每个ID找到CHG的SUM。

这是我当前的代码(注意:列标题与上面的数据不同,用于格式化。另外,我不能写入此数据库,因此只能以查询格式写入)

SELECT
     *,  
     CASE 
        WHEN MratingNum = 0 OR
             LAG(MratingNum) OVER (OVER BY MAST_ISSU_NUM, RATG_DATETIME) = 0 OR 
             MAST_ISSU_NUM <> LAG(MAST_ISSU_NUM) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME) --OR
            --LAG(MratingNum) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME) < 12 OR  --By Credit Rating
            --LAG(MratingNum) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME) < 18
           THEN NULL 
           ELSE CAST(MratingNum AS INT) - LAG(MratingNum) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME)
    END AS CHG,
    DATEDIFF(month, RATG_DATETIME, RATG_END_DATETIME) AS DateCHG 
FROM
    MOODYS_DRD.dbo.DEBT_RATG AS t1
LEFT JOIN
    sandbox.dbo.RatingMap AS t2 ON t1.RATG_TXT = t2.MratingValue
WHERE 
    RATG_TYP_CD = 'LT'
ORDER BY 
    MAST_ISSU_NUM, RATG_DATETIME

所以例如输出看起来像这样:

ID S_DATE   .... SumCHG
1  1/26/2001....   NULL
1  2/27/2001....   NULL
1  3/28/2001....   2
1  1/10/2003....   NULL
1  3/3/2004 ....   NULL

我假设最好的方法是计算DateCHG的滚动总和,其中它小于3,然后SUM CHG列?谢谢大家!

编辑:这是相当复杂的,所以让我尝试另一种提问的方式。对于每条记录,我想回顾一下,并在S_DATE的3个月内找到CHG的总和。对于3/28/2001,这将包括2/01和1/01。 MNum从7变为9,因此CHG的SUM为2.但是从3/04开始,过去3个月没有变化,因此返回NULL。我显然想按ID进行此操作,所以不要在ID 2到1之间重叠3个月。希望现在更有意义吗?

1 个答案:

答案 0 :(得分:0)

t0t用于设置数据。

with    t0
          as ( select   *
               from     ( values ( 1, '1/26/2001', '2/26/2001', 7, null, 1),
                        ( 1, '2/27/2001', '3/27/2001', 8, 1, 1),
                        ( 1, '3/28/2001', '1/9/2003', 9, 1, 21),
                        ( 1, '1/10/2003', '3/2/2004', 11, 2, 14),
                        ( 1, '3/3/2004', '10/14/2004', 10, -1, 7),
                        ( 1, '10/15/2004', '6/22/2005', 9, -1, 8),
                        ( 1, '6/23/2005', '3/9/2008', 8, -1, 33),
                        ( 1, '3/10/2008', '1899-12-30', 0, null, -1299),
                        ( 2, '9/23/1993', '9/11/2000', 3, null, 84),
                        ( 2, '1/1/1999', '12/31/1998', 3, 0, -1),
                        ( 2, '9/12/2000', '11/13/2001', 2, -1, 14),
                        ( 2, '11/14/2001', '1899-12-30', 0, null, -1223) ) t ( ID, S_DATE, END_DATE, MNum, CHG, DateCHG )
             ),
        t as ( select   t0.ID ,
                        cast(t0.S_DATE as date) S_DATE ,
                        cast(t0.END_DATE as date) END_DATE ,
                        t0.MNum ,
                        t0.CHG ,
                        t0.DateCHG
               from     t0
             )
    select  case when Cnt >= 3 then p.CHG
            end SumCHG,
            *
    from    t
            outer apply ( select    sum(u.CHG) CHG ,
                                    count(*) Cnt
                          from      t u
                          where     u.ID = t.ID
                                    and u.S_DATE between dateadd(month, -3,
                                                              t.S_DATE)
                                                 and     t.S_DATE
                        ) p
    order by t.ID ,
        t.S_DATE;

将CTE用于表格,

;with t as (
SELECT
     *,  
     CASE 
        WHEN MratingNum = 0 OR
             LAG(MratingNum) OVER (OVER BY MAST_ISSU_NUM, RATG_DATETIME) = 0 OR 
             MAST_ISSU_NUM <> LAG(MAST_ISSU_NUM) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME) --OR
            --LAG(MratingNum) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME) < 12 OR  --By Credit Rating
            --LAG(MratingNum) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME) < 18
           THEN NULL 
           ELSE CAST(MratingNum AS INT) - LAG(MratingNum) OVER (ORDER BY MAST_ISSU_NUM, RATG_DATETIME)
    END AS CHG,
    DATEDIFF(month, RATG_DATETIME, RATG_END_DATETIME) AS DateCHG 
FROM
    MOODYS_DRD.dbo.DEBT_RATG AS t1
LEFT JOIN
    sandbox.dbo.RatingMap AS t2 ON t1.RATG_TXT = t2.MratingValue
WHERE 
    RATG_TYP_CD = 'LT'
)
    select  case when Cnt >= 3 then p.CHG
            end SumCHG,
            *
    from    t
            outer apply ( select    sum(u.CHG) CHG ,
                                    count(*) Cnt
                          from      t u
                          where     u.ID = t.ID
                                    and u.S_DATE between dateadd(month, -3,
                                                              t.S_DATE)
                                                 and     t.S_DATE
                        ) p
    order by t.ID ,
        t.S_DATE;