Промежуточная сумма с пропущенными датами - PullRequest
0 голосов
/ 21 февраля 2020

У меня есть таблица данных, подобная этой:

PeriodYearMonth Reg      PartNo             ComponentRemovals   RunningRemovals
2019 10         G-NHVP   109-0740V01-137    1                    1
2019 11         G-NHVP   109-0740V01-137    1                    2  
2019 12         G-NHVP   109-0740V01-137    1                    3
2020 01         G-NHVP   109-0740V01-137    1                    4
2019 10         OO-NSF   11-13354P          1                    1
2019 09         G-NHVR   11-13354P          2                    2 
2019 10         OY-HMV   11-13354P          1                    1

В последнем столбце я вычислил 7-месячную промежуточную сумму удалений для PartNo и Reg. Для этого я сделал следующий код:

/****** Find Running Component Removals ******/
SELECT  [PeriodYearMonth]
      ,[Reg]
      ,[PartNo]
      ,[ComponentRemovals]
      ,sum(sum(ComponentRemovals)) over (Partition by [Reg], PartNo Order By PeriodYearMonth, PeriodYearMonth rows between 6 preceding and current row) as RunningRemovals
      ,[ConfirmedFailures]
      , sum(sum(ConfirmedFailures)) over (Partition by [Reg], PartNo Order By PeriodYearMonth, PeriodYearMonth rows between 6 preceding and current row) as RunningFailures

  FROM [RALNHVTST].[dbo].[vtRelRepComponentsRemovalsByPartNo]

  Group by Reg, PartNo, ComponentRemovals, ConfirmedFailures, PeriodYearMonth
  Order by PartNo

Однако, поскольку не все месяцы включены в столбец PeriodYearMonth, результаты неверны. Я видел онлайн-решения для простых случаев, но для меня сложнее всего то, что мне нужна запись для каждого PartNo, каждого Reg и каждого месяца.

Любая помощь будет принята с благодарностью.

Привет

Ответы [ 2 ]

0 голосов
/ 22 февраля 2020

Чтобы решить эту проблему, вам нужно создать отдельные производные таблицы со всеми значениями PeriodYearMonth (сгенерированными с использованием рекурсивного CTE) и отдельными парами Reg и PartNo и CROSS JOIN их друг для друга, чтобы получить все комбинации столбцов. Затем эту объединенную таблицу можно * LEFT JOIN преобразовать в исходную таблицу, чтобы получить ComponentRemovals для каждого Reg, PartNo и PeriodYearMonth, и затем их можно суммировать с помощью оконной функции:

WITH CTE AS (
  SELECT CONVERT(DATE, CONCAT(REPLACE(MIN(PeriodYearMonth), ' ', '-'), '-01'), 23)  AS date, 
         CONVERT(DATE, CONCAT(REPLACE(MAX(PeriodYearMonth), ' ', '-'), '-01'), 23)  AS max_date
  FROM vtRelRepComponentsRemovalsByPartNo
  UNION ALL
  SELECT DATEADD(MONTH, 1, date), max_date
  FROM CTE
  WHERE date < max_date
)
SELECT FORMAT(CTE.date, 'yyyy MM') AS PeriodYearMonth
     , rp.Reg
     , rp.PartNo
     , COALESCE(v.ComponentRemovals, 0) AS ComponentRemovals
     , SUM(COALESCE(v.ComponentRemovals, 0)) OVER (PARTITION BY rp.Reg, rp.PartNo ORDER BY FORMAT(CTE.date, 'yyyy MM')
                                                   ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS RunningRemovals
FROM CTE
CROSS JOIN (SELECT DISTINCT Reg, PartNo FROM vtRelRepComponentsRemovalsByPartNo) rp
LEFT JOIN vtRelRepComponentsRemovalsByPartNo v
       ON v.PeriodYearMonth = FORMAT(CTE.date, 'yyyy MM')
      AND v.Reg = rp.Reg
      AND v.PartNo = rp.PartNo
ORDER BY rp.Reg, rp.PartNo, CTE.date

Вывод

PeriodYearMonth     Reg     PartNo              ComponentRemovals   RunningRemovals
2019 09             G-NHVP  109-0740V01-137     0                   0
2019 10             G-NHVP  109-0740V01-137     1                   1
2019 11             G-NHVP  109-0740V01-137     1                   2
2019 12             G-NHVP  109-0740V01-137     1                   3
2020 01             G-NHVP  109-0740V01-137     1                   4
2019 09             G-NHVR  11-13354P           2                   2
2019 10             G-NHVR  11-13354P           0                   2
2019 11             G-NHVR  11-13354P           0                   2
2019 12             G-NHVR  11-13354P           0                   2
2020 01             G-NHVR  11-13354P           0                   2
2019 09             OO-NSF  11-13354P           0                   0
2019 10             OO-NSF  11-13354P           1                   1
2019 11             OO-NSF  11-13354P           0                   1
2019 12             OO-NSF  11-13354P           0                   1
2020 01             OO-NSF  11-13354P           0                   1
2019 09             OY-HMV  11-13354P           0                   0
2019 10             OY-HMV  11-13354P           1                   1
2019 11             OY-HMV  11-13354P           0                   1
2019 12             OY-HMV  11-13354P           0                   1
2020 01             OY-HMV  11-13354P           0                   1

Демонстрация по SQLFiddle

Обратите внимание, что если все PeriodYearMonth интересующие значения присутствуют в vtRelRepComponentsRemovalsByPartNo вы можете просто использовать SELECT DISTINCT ... подзапрос для получения этих значений, а не рекурсивный CTE например

SELECT d.PeriodYearMonth
     , rp.Reg
     , rp.PartNo
     , COALESCE(v.ComponentRemovals, 0) AS ComponentRemovals
     , SUM(COALESCE(v.ComponentRemovals, 0)) OVER (PARTITION BY rp.Reg, rp.PartNo ORDER BY d.PeriodYearMonth
                                                   ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS RunningRemovals
FROM (SELECT DISTINCT PeriodYearMonth FROM vtRelRepComponentsRemovalsByPartNo) d
CROSS JOIN (SELECT DISTINCT Reg, PartNo FROM vtRelRepComponentsRemovalsByPartNo) rp
LEFT JOIN vtRelRepComponentsRemovalsByPartNo v
       ON v.PeriodYearMonth = d.PeriodYearMonth
      AND v.Reg = rp.Reg
      AND v.PartNo = rp.PartNo
ORDER BY rp.Reg, rp.PartNo, d.PeriodYearMonth

Демонстрация по SQLFiddle

0 голосов
/ 21 февраля 2020

В последнем столбце я вычислил текущую сумму изъятий для PartNo и Reg за последние 7 месяцев.

Снятие предложения оконного фильтра и фильтра:

select [PeriodYearMonth], [Reg], [PartNo], [ComponentRemovals],
        sum(sum(ComponentRemovals)) over (Partition by [Reg], PartNo Order By PeriodYearMonth, PeriodYearMonth) as RunningRemovals
        [ConfirmedFailures],
        sum(sum(ConfirmedFailures)) over (Partition by [Reg], PartNo Order By PeriodYearMonth, PeriodYearMont) as RunningFailures
from [RALNHVTST].[dbo].[vtRelRepComponentsRemovalsByPartNo]
where PeriodYearMonth >= format(dateadd(month, -7, getdate()), 'yyyy MM')
group by Reg, PartNo, ComponentRemovals, ConfirmedFailures, PeriodYearMonth
Order by PartNo
...