我的表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
值中计算'2018-01'
中的交易商'A'
,它应该与YTD
相同。
如果要在MTD
中计算经销商'A'
的YTD
值,则MTD
值应等于'2018-06'
中的YTD
值减去'2018-05'
中的YTD
值。'2018-06'
中的QTD值应等于'2018-06'
中的YTD
值减去'2018-03'
中的YTD
值,或等于'2018-03'
中的和MTD
值(2018-04,2018-05,2018-06)。
对其他经销商,如B,同样的规则。
如何编写SQL以实现此目的?
发布于 2019-01-12 04:48:20
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
这里是db<>fiddle。
发布于 2019-01-12 02:58:41
下面的查询应该完成此工作。它使用一个CTE将varchar列转换为date,然后几个联接来恢复要比较的值。
我在这把竖琴中测试了它,输出与您的预期结果相匹配。
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
。
https://stackoverflow.com/questions/54158329
复制相似问题