oracle ytd,How to calculate MTD and QTD by YTD value in Oracle

可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:

问题:

There are some data in my table t1 looks like below:

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

... ... ...

then I want to write a SQL to query this table and get below result:

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' means Year to date

'MTD' means Month to date

'QTD' means Quarter to date

So if I want to calculate MTD and QTD value for dealer 'A' in '2018-01', it should be the same as YTD.

If I want to calculate MTD value for dealer 'A' in '2018-06', MTD value should equal to YTD value in '2018-06' minus YTD value in '2018-05'. And the QTD value in '2018-06' should equal to YTD value in '2018-06' minus YTD value in '2018-03' or equal to sum MTD value in (2018-04,2018-05,2018-06)

The same rule for other dealers such as B.

How can I write the SQL to achieve this purpose?

回答1:

The QTD calculation is tricky, but you can do this query without subqueries. The basic idea is to do a lag() for the monthly value. Then use a max() analytic function to get the YTD value at the beginning of the quarter.

Of course, the first quarter of the year has no such value, so a coalesce() is needed.

Try this:

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

Here is a db<>fiddle.

回答2:

The following query should do the job. It uses a CTE that translates the varchar date column to dates, and then a few joins to recover the value to compare.

I tested it in this db fiddle and the output matches your expected results.

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 is a reserved word in most RDBMS (including Oracle), I renamed that column to my_date in the query.

回答3:

You can use lag() windows analytic and sum() over .. aggregation functions as :

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";


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部