使用 oracle 获取过去 12 个月的计数及其差异

Posted

技术标签:

【中文标题】使用 oracle 获取过去 12 个月的计数及其差异【英文标题】:fetch last 12 months count and their variance using oracle 【发布时间】:2020-05-22 13:25:28 【问题描述】:
with sales as
(
select  COUNT(sale) As Number_of_sale, 
TO_CHAR(dates,'YYYY-MON') As Period

  from orders
    where dates between date '2020-03-01' and date '2020-03-31'
group by TO_CHAR(dates,'YYYY-MON') 

union all
select  COUNT(sale) As Number_of_sale,
TO_CHAR(dates,'YYYY-MON') As Period

  from orders
  where dates between date '2020-04-01' and date '2020-04-30'
group by TO_CHAR(dates,'YYYY-MON') 

)
select  Number_of_sale, period,
case when to_char(round((Number_of_sale-lag(Number_of_sale,1, Number_of_sale) over (order by period ))/ Number_of_sale*100,2), 'FM999999990D9999') <0 
then to_char(round(abs( Number_of_sale-lag(Number_of_sale,1, Number_of_sale) over (order by period ))/ Number_of_sale*100,2),'FM999999990D9999')||'%'||'  (Increase) '
when to_char(round((Number_of_sale-lag(Number_of_sale,1,Number_of_sale) over (order by period ))/Number_of_sale*100,2),'FM999999990D9999')>0 
then to_char(round(abs(Number_of_sale-lag(Number_of_sale,1, Number_of_sale) over (order by period ))/Number_of_sale*100,2),'FM999999990D9999')||'%'||'  (Decrease) '
END as variances
        from sales
        order by variances asc;

我得到的输出

Number_of_sale  |  Period        |Variances
   50           |   2020-Mar         |  100%(increase)
   100          |   2020-Apr         |  Null

我需要的输出:- 我需要过去 12 个月的数据,以及它们与上个月的差异。

【问题讨论】:

请定义方差的含义。您显然没有使用标准的统计定义。样本数据和期望的结果也会有所帮助。 Number_of_sale |期间 |方差 500 | 2020年四月 | 20%(增加(根据 2019 年 3 月的数据)) 375 | 2020-3月 | 0.2%(增加(根据 2019 年 2 月的数据)) 360 | 2020 年 2 月 |空等等... acc。到我的查询..我只获取两个月的记录,我需要过去 12 个月.. 记录 也许你应该在dates BETWEEN x AND y 里放两个多月的时间! 【参考方案1】:

首先,您需要学习使用日期作为日期,只有在极少数情况下才需要转换为字符串(最终显示结果除外)。这不是其中的一个。你所拥有的一切都可以作为日期。 这样一来,您抱怨您想要 12 个月,但您的查询只选择 2 个月。如果您想要最后 12 个,则必须选择所有 12 个。您说您想要方差,但您不是在计算统计方差,而是计算月间差异(如果 1 个月与前一个月相比有多大差异)。

with parms  as (select trunc(date '&period_end_date','mon') dt from dual) 
   , sales as 
    ( select count(*) cnt 
           , trunc(dates,'mon') period
        from orders 
        cross join parms
       where trunc(dates,'mon') between add_months(dt, -12) 
                                         and last_day(dt)
       group by trunc(dates,'mon')
    ) 
select to_char(period, 'yyyy-Mon')  period
     , cnt                          number_of_sales 
     , to_char (round(abs(cnt - lag(cnt) over (order by period)) / cnt*100,2),'FM999999990D9999') ||
         case when cnt - lag(cnt) over (order by period) < 0 then ' %(Increase)'
              when cnt - lag(cnt) over (order by period) > 0 then ' %(Decrease)'
              else null
         end variances
  from sales  
order by variances asc;

工作原理 parms cte(在oracle'subquery factoring'中)基本上是因为我很懒,不想多次输入参数值。但它还有一个优点,即无论输入的实际日期如何,它都会“返回”当月的 1 日。 sales cte 计算前 12 个月 (add_months(dt, -12)) 和参数日期的最后一天 (last_day(dt)) 的每个月的销售额。这些函数中的每一个都会自动调整为 2 月 29 日和不同的各个月份的天数。它获取将日期列截断为每月第一天后每个月的销售计数。 然后,主查询使用简化的情况计算月与月的差异以确定增加或减少(保持不变,但我认为它可能会被反转和/或您需要领先而不是滞后)。 免责声明:由于您实际上并未提供表定义而不是示例数据,因此未经过测试。

【讨论】:

【参考方案2】:

您的查询的 WITH 位包含一些多余的联合,它可能会排除带有时间段结束时间的日期。请考虑一下:

select  COUNT(sale) As Number_of_sale, 
TO_CHAR(dates,'YYYY-MON') As Period

  from orders
    where dates >= date '2019-03-01' and dates < date '2020-03-01'
group by TO_CHAR(dates,'YYYY-MON') 



您不需要将连续的日期范围合并在一起,只需使用更大的日期范围 - 您的抱怨是您只有两个月,但这就是您所要求的! (从3月1日到3月31日,从4月1日到30日,是两个月)

【讨论】:

以上是关于使用 oracle 获取过去 12 个月的计数及其差异的主要内容,如果未能解决你的问题,请参考以下文章

使用图表显示过去 12 个月的注册用户分析

MySQL 获取按月分组的过去 12 个月的数量

每月每个类别的分组计数(当前月份与过去几个月的剩余时间)在 pandas 的单独列中

使用Scala从给定月份获取前12个月的月底日期

SQL 通过微秒时间戳获取过去几个月的行?

如何使用月份名称获取最近 3 个月的计数,如果该月份没有记录需要使用月份名称获取 0 [重复]