Как рассчитать MTD и QTD по значению YTD в Oracle - PullRequest
0 голосов
/ 12 января 2019

Есть некоторые данные в моей таблице t1, как показано ниже:

date    dealer   YTD_Value    
2018-01   A       1100    
2018-02   A       2000
2018-03   A       3000
2018-04   A       4200
2018-05   A       5000
2018-06   A       5500
2017-01   B        100
2017-02   B        200
2017-03   B        500    
...      ...       ...

тогда я хочу написать SQL для запроса этой таблицы и получить результат ниже:

date    dealer   YTD_Value    MTD_Value       QTD_Value
2018-01   A       1100           1100           1100
2018-02   A       2000            900           2000
2018-03   A       3000           1000           3000
2018-04   A       4200           1200           1200
2018-05   A       5000            800           2000
2018-06   A       5500            500           2500
2017-01   B        100            100            100
2017-02   B        200            100            200
2017-03   B        550            350            550    
...       ...      ...            ...            ...

'YTD' означает год до даты
'MTD' означает месяц до даты
'QTD' означает квартал на сегодняшний день

Так что, если я хочу вычислить значение MTD и QTD для дилера 'A' в '2018-01', оно должно быть таким же, как YTD.

Если я хочу вычислить значение MTD для дилера 'A' в '2018-06', значение MTD должно равняться YTD значению в '2018-06' минус YTD значении в '2018-05'. И значение QTD в '2018-06' должно быть равно YTD значению в '2018-06' минус YTD значению в '2018-03' или равно сумме MTD в (2018-04,2018-05,2018-06)

То же правило для других дилеров, таких как B.

Как мне написать SQL для достижения этой цели?

Ответы [ 3 ]

0 голосов
/ 12 января 2019

Вы можете использовать lag() аналитику окон и sum() over .. функции агрегирования как:

select "date",dealer,YTD_Value,MTD_Value,
       sum(MTD_Value) over (partition by qt order by "date")
          as QTD_Value 
  from
  (
   with t("date",dealer,YTD_Value) as
   (  
    select '2018-01','A',1100 from dual union all    
    select '2018-02','A',2000 from dual union all
    select '2018-03','A',3000 from dual union all
    select '2018-04','A',4200 from dual union all
    select '2018-05','A',5000 from dual union all
    select '2018-06','A',5500 from dual union all
    select '2017-01','B', 100 from dual union all
    select '2017-02','B', 200 from dual union all
    select '2017-03','B', 550 from dual
   ) 
   select t.*,
          t.YTD_Value - nvl(lag(t.YTD_Value) 
          over (partition by substr("date",1,4) order by substr("date",1,4) desc, "date"),0) 
             as MTD_Value,
          substr("date",1,4)||to_char(to_date("date",'YYYY-MM'),'Q')
             as qt,
          substr("date",1,4) as year
        from t
      order by year desc, "date"
   )     
  order by year desc, "date";

Rextester Demo

0 голосов
/ 12 января 2019

Расчет QTD сложен, но вы можете сделать этот запрос без подзапросов. Основная идея состоит в том, чтобы сделать lag() для месячного значения. Затем используйте аналитическую функцию max(), чтобы получить значение YTD в начале квартала.

Конечно, первый квартал года не имеет такого значения, поэтому требуется coalesce().

Попробуйте это:

with t(dte, dealer, YTD_Value) as (  
      select '2018-01', 'A', 1100 from dual union all    
      select '2018-02', 'A', 2000 from dual union all
      select '2018-03', 'A', 3000 from dual union all
      select '2018-04', 'A', 4200 from dual union all
      select '2018-05', 'A', 5000 from dual union all
      select '2018-06', 'A', 5500 from dual union all
      select '2017-01', 'B', 100 from dual union all
      select '2017-02', 'B', 200 from dual union all
      select '2017-03', 'B', 550 from dual
   ) 
select t.*,
       (YTD_Value - lag(YTD_Value, 1, 0) over (partition by substr(dte, 1, 4) order by dte)) as MTD_Value,
       (YTD_Value -
        coalesce(max(case when substr(dte, -2) in ('03', '06', '09') then YTD_VALUE end) over
                                   (partition by substr(dte, 1, 4) order by dte rows between unbounded preceding and 1 preceding
                                   ), 0
                )
       ) as QTD_Value
from t
order by 1

Здесь - это дБ <> скрипка.

0 голосов
/ 12 января 2019

Следующий запрос должен выполнить эту работу. Он использует CTE, который переводит столбец даты varchar в даты, а затем несколько соединений для восстановления значения для сравнения.

Я проверил это в этой скрипте дБ , и результат соответствует вашим ожидаемым результатам.

WITH cte AS (
    SELECT TO_DATE(my_date, 'YYYY-MM') my_date, dealer, ytd_value FROM my_table
)
SELECT
    TO_CHAR(ytd.my_date, 'YYYY-MM') my_date,
    ytd.ytd_value,
    ytd.dealer,
    ytd.ytd_value - NVL(mtd.ytd_value, 0) mtd_value,
    ytd.ytd_value - NVL(qtd.ytd_value, 0) qtd_value
FROM 
    cte ytd
    LEFT JOIN cte mtd ON mtd.my_date = ADD_MONTHS(ytd.my_date, -1) AND mtd.dealer = ytd.dealer
    LEFT JOIN cte qtd ON qtd.my_date = ADD_MONTHS(TRUNC(ytd.my_date, 'Q'), -1)  AND mtd.dealer = qtd.dealer
ORDER BY dealer, my_date

PS: date является зарезервированным словом в большинстве СУБД (включая Oracle), я переименовал этот столбец в my_date в запросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...