使用 oracle 获取最近 12 个月的计数及其方差
fetch last 12 months count and their variance using oracle
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 个月的数据以及它们与上个月的差异。
您查询的 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日,是两个月)
首先,您需要学习使用日期作为日期,只有在极少数情况下才需要转换为字符串(最终显示结果除外)。这不是其中的一个。你拥有的一切都可以作为日期。
有了这个,你抱怨你想要 12 个月,但你的查询只有 selects 2 个月。如果你想要最后 12 个,你必须 select 所有 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 (in oracle 'subquery factoring') 基本上是因为我比较懒,不想多次输入参数值。但它也有一个优点,无论输入的实际日期是 'returns' 这个月的 1 号。
sales cte 计算前 12 个月 (add_months(dt, -12)) 和参数日期 (last_day(dt) 的最后一天的每个月的销售额。这些函数中的每一个自动调整 2 月 29 日和个别月份的不同天数。它在将日期列截断到月初后获取每个月的销售计数。
然后主查询使用简化的案例计算月与月的差异以确定增加或减少(保持不变但我认为它可能会逆转and/or你需要领先而不是滞后)。
免责声明: 因为您实际上没有提供 table 定义而不是样本数据,所以它还没有经过测试。
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 个月的数据以及它们与上个月的差异。
您查询的 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日,是两个月)
首先,您需要学习使用日期作为日期,只有在极少数情况下才需要转换为字符串(最终显示结果除外)。这不是其中的一个。你拥有的一切都可以作为日期。 有了这个,你抱怨你想要 12 个月,但你的查询只有 selects 2 个月。如果你想要最后 12 个,你必须 select 所有 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 (in oracle 'subquery factoring') 基本上是因为我比较懒,不想多次输入参数值。但它也有一个优点,无论输入的实际日期是 'returns' 这个月的 1 号。
sales cte 计算前 12 个月 (add_months(dt, -12)) 和参数日期 (last_day(dt) 的最后一天的每个月的销售额。这些函数中的每一个自动调整 2 月 29 日和个别月份的不同天数。它在将日期列截断到月初后获取每个月的销售计数。
然后主查询使用简化的案例计算月与月的差异以确定增加或减少(保持不变但我认为它可能会逆转and/or你需要领先而不是滞后)。
免责声明: 因为您实际上没有提供 table 定义而不是样本数据,所以它还没有经过测试。