首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用Oracle中的YTD值计算MTD和QTD

如何用Oracle中的YTD值计算MTD和QTD
EN

Stack Overflow用户
提问于 2019-01-12 09:36:19
回答 2查看 4.5K关注 0票数 2

我的表t1中有一些数据如下所示:

代码语言:javascript
运行
复制
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来查询这个表并得到下面的结果:

代码语言:javascript
运行
复制
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'是指到目前为止的季度

因此,如果我想在MTDQTD值中计算'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以实现此目的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-12 12:48:20

QTD的计算很棘手,但是您可以在没有子查询的情况下完成这个查询。基本思想是为每月的值做一个lag()。然后使用max()解析函数在季度开始时得到YTD值。

当然,今年第一季度没有这样的价值,因此需要一个coalesce()

试试这个:

代码语言:javascript
运行
复制
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。

票数 2
EN

Stack Overflow用户

发布于 2019-01-12 10:58:41

下面的查询应该完成此工作。它使用一个CTE将varchar列转换为date,然后几个联接来恢复要比较的值。

我在这把竖琴中测试了它,输出与您的预期结果相匹配。

代码语言:javascript
运行
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54158329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档