2016-12-27 4 views
0

Я новичок в SQL Server и задаю вопрос о суммировании по вычисленной строке с условным выражением.SQL Server: сумма вычисляемой строки в течение N месяцев

Мои данные организованы следующим образом:

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 & датой_окончания. Я хотел бы найти СУММ CHG для каждого идентификатора, где CHG происходит в течение 3 месяцев с предыдущей даты.

Вот мой текущий код (Примечание: Заголовки столбцов отличаются от приведенных выше данных для целей форматирования Кроме того, я не могу писать в эту базу данных, так только в формате запроса.)

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, а затем просуммировать столбец CHG? Спасибо всем!

EDIT: Это довольно сложно, поэтому позвольте мне попробовать другой способ задать вопрос. Для каждой записи я хочу оглянуться назад и найти СУММУ CHG в течение 3 месяцев после S_DATE. Для 3/28/2001 это будет включать 2/01 и 1/01. MNum отправился с 7 до 9, так что SUM CHG будет 2. Однако с 3/04 за последние 3 месяца изменений не было, поэтому возвратите NULL. Я, очевидно, хочу сделать это за ID, поэтому не хочу перекрывать 3 месяца от ID 2 до 1. Надеюсь, теперь это имеет больше смысла?

+0

Как ваш выходной пример того, что вы просили? Вы запросили суммарную сумму SumChg для каждого идентификатора, так что у вас будет только один ID = 1. – Edward

+0

@Edward каждым идентификатором означает, что я не хочу пересекаться между идентификаторами. Я хочу посмотреть на каждую строку и найти сумму за все, что было в течение предыдущих 3 месяцев. Если есть только 2 строки на идентификатор, и они находятся на расстоянии 6 месяцев, я хочу вернуть NULL. Если есть 20 строк для идентификатора, и есть 2 'clumps' данных, где они находятся в течение 3 месяцев, я хочу найти сумму для каждого из этих комков. Надеюсь, что это имеет смысл? – user5854307

+0

нет действительно. Что вы подразумеваете под компу? перекрывая, я думаю, вы имеете в виду, что вы не хотите смешивать ID = 1 с ID = 2. Пожалуйста, проверьте мой ответ и сообщите мне, что он не делает, вы пытаетесь выполнить. – Edward

ответ

0

t0 и t используются для настройки данных.

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; 
+0

Я чувствую, что это на правильном пути, но я не уверен, как включить в мой существующий код? Я все еще очень новичок в SQL и не знаю, где синтаксис принадлежит ... – user5854307

+0

Просто начните с части 'select'. Измените 't' на' yourDataSource t'. – ca9163d9

+0

Как вас зовут btw? – ca9163d9