[英]How to calculate MTD and QTD by YTD value in Oracle
There are some data in my table t1 looks like below: 我的表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
... ... ...
then I want to write a SQL to query this table and get below result: 然后我想编写一个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'
means Year to date 'YTD'
是指年初至今
'MTD'
means Month to date 'MTD'
表示迄今为止的月份
'QTD'
means Quarter to date 'QTD'
表示迄今为止的季度
So if I want to calculate MTD
and QTD
value for dealer 'A'
in '2018-01'
, it should be the same as YTD
. 因此,如果我想计算
'2018-01'
经销商'A'
MTD
和QTD
值,则应与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'
. 如果我想计算
MTD
的经销商价值'A'
在'2018-06'
, MTD
值应等于YTD
值'2018-06'
负YTD
中值'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) 并在QTD值
'2018-06'
应等于YTD
在值'2018-06'
减去YTD
在值'2018-03'
或等于求和MTD
中值(2018-04,2018-05,2018-06)
The same rule for other dealers such as B. 对于其他交易商(例如B)也有相同的规定。
How can I write the SQL to achieve this purpose? 我该如何编写SQL来实现此目的?
The QTD calculation is tricky, but you can do this query without subqueries. QTD的计算很棘手,但是您可以在没有子查询的情况下执行此查询。 The basic idea is to do a
lag()
for the monthly value. 基本思想是对月度值进行
lag()
。 Then use a max()
analytic function to get the YTD value at the beginning of the quarter. 然后使用
max()
分析函数在季度开始时获取YTD值。
Of course, the first quarter of the year has no such value, so a coalesce()
is needed. 当然,一年的第一季度没有这样的值,因此需要
coalesce()
。
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
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.
它使用CTE将varchar date列转换为日期,然后进行一些联接以恢复要比较的值。
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. PS:
date
是大多数RDBMS(包括Oracle)中的保留字,我在查询中将该列重命名为my_date
。
You can use lag()
windows analytic and sum() over ..
aggregation functions as : 您可以
sum() over ..
聚合函数使用lag()
windows analytic和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";
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.