按月滚动季度计算,同时使用另一列进行分组
Rolling Quarter Calculation by Month While Using Another Column to group by
我正在尝试计算季度时间段的滚动百分比。通过 sql 的示例数据如下:
create table #demo (Month char(7), Type varchar(10), Mileage int);
--low
insert into #demo values ('2021-05', 'low', 5000);
insert into #demo values ('2021-06', 'low', 15000);
insert into #demo values ('2021-07', 'low', 3000);
insert into #demo values ('2021-08', 'low', 3500);
-- med
insert into #demo values ('2021-05', 'med', 6789);
insert into #demo values ('2021-06', 'med', 12876);
insert into #demo values ('2021-07', 'med', 1578);
insert into #demo values ('2021-08', 'med', 3500);
--high
insert into #demo values ('2021-05', 'high', 5000);
insert into #demo values ('2021-06', 'high', 1500);
insert into #demo values ('2021-07', 'high', 2700);
insert into #demo values ('2021-08', 'high', 2968);
Month Type Mileage
2021-05 high 5000
2021-05 low 5000
2021-05 med 6789
2021-06 high 1500
2021-06 low 15000
2021-06 med 12876
2021-07 high 2700
2021-07 low 3000
2021-07 med 1578
2021-08 high 2968
2021-08 low 3500
2021-08 med 3500
我的目标是获取这些数据并分别计算每个类别的滚动 3 个月百分比。
示例:
对于 2021 年的前 3 个月,我希望获得 2021-05、2021-06、2021-07 的总和(低里程)、总和(中里程)、总和(高里程),然后将每个总和除以总和这三个月(所有类别)。我想 PIVOT 解决方案在这里是理想的。我只是不确定该怎么做。
所以我希望看到如下滚动总数:
Month ThreeMonth_TotalMileage ThreeMonth_Low ThreeMonth_Med ThreeMonth_High
2021-05 NULL NULL NULL NULL
2021-06 NULL NULL NULL NULL
2021-07 53443 23000 21243 9200
2021-08 46622 18800 17954 7168
例如ThreeMonth_TotalMileage 是 2021-05、2021-06、2021-07 所有里程的总和。这只会显示为 2021-07 年的 运行 总数,因为我们有 3 个月的历史记录,我们可以从中计算总和,否则我希望它为空。
3Month_Low 是 2021-05、2021-06、2021-07 的所有低里程总和,基本上包括当前月份加上每个计算的前 2 个。
关于如何尝试使用 SQL 服务器完成此操作的任何想法?谢谢!
您可以使用 Ordered Analytical Function 来实现。思路是求累计和。
要将数据从行旋转到列,您可以使用 CASE
和 MAX
。
select
Month
,Max(case when Type='low' then Mileage end) as Month_Low
,Max(case when Type='med' then Mileage end)as Month_Med
,Max(case when Type='high' then Mileage end) as Month_High
,case when ROW_NUMBER() over(order by Month asc)>=3 Then 1 end as is_3month_data_present
from #demo
group by month
Month
Month_Low
Month_Med
Month_High
is_3month_data_present
2021-05
5000
6789
5000
null
2021-06
15000
12876
1500
null
2021-07
3000
1578
2700
1
2021-08
3500
3500
2968
1
下面的 SQL 应该给出所需的最终结果。
select
Month
,case when is_3month_data_present=1 then Sum(Month_Low+Month_Med+Month_High) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_TotalMileage
,case when is_3month_data_present=1 then Sum(Month_Low) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_Low
,case when is_3month_data_present=1 then Sum(Month_Med ) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_Med
,case when is_3month_data_present=1 then Sum(Month_High) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_High
from
(select
Month
,Max(case when Type='low' then Mileage end) as Month_Low
,Max(case when Type='med' then Mileage end)as Month_Med
,Max(case when Type='high' then Mileage end) as Month_High
,case when ROW_NUMBER() over(order by Month asc)>=3 Then 1 end as is_3month_data_present
from #demo
group by Month
)stg
输出:
Month
ThreeMonth_TotalMileage
ThreeMonth_Low
ThreeMonth_Med
ThreeMonth_High
2021-05
null
null
null
2021-06
null
null
null
2021-07
53443
23000
21243
9200
2021-08
46622
21500
17954
7168
注意:根据给定的数据集,问题中提供的预期输出是错误的。 ThreeMonth_low 是错误的,其余都是正确的。对于 2021-07,实际值应为 23000
而不是 20300
。
DB Fiddle: Try it here
我正在尝试计算季度时间段的滚动百分比。通过 sql 的示例数据如下:
create table #demo (Month char(7), Type varchar(10), Mileage int);
--low
insert into #demo values ('2021-05', 'low', 5000);
insert into #demo values ('2021-06', 'low', 15000);
insert into #demo values ('2021-07', 'low', 3000);
insert into #demo values ('2021-08', 'low', 3500);
-- med
insert into #demo values ('2021-05', 'med', 6789);
insert into #demo values ('2021-06', 'med', 12876);
insert into #demo values ('2021-07', 'med', 1578);
insert into #demo values ('2021-08', 'med', 3500);
--high
insert into #demo values ('2021-05', 'high', 5000);
insert into #demo values ('2021-06', 'high', 1500);
insert into #demo values ('2021-07', 'high', 2700);
insert into #demo values ('2021-08', 'high', 2968);
Month Type Mileage
2021-05 high 5000
2021-05 low 5000
2021-05 med 6789
2021-06 high 1500
2021-06 low 15000
2021-06 med 12876
2021-07 high 2700
2021-07 low 3000
2021-07 med 1578
2021-08 high 2968
2021-08 low 3500
2021-08 med 3500
我的目标是获取这些数据并分别计算每个类别的滚动 3 个月百分比。
示例: 对于 2021 年的前 3 个月,我希望获得 2021-05、2021-06、2021-07 的总和(低里程)、总和(中里程)、总和(高里程),然后将每个总和除以总和这三个月(所有类别)。我想 PIVOT 解决方案在这里是理想的。我只是不确定该怎么做。
所以我希望看到如下滚动总数:
Month ThreeMonth_TotalMileage ThreeMonth_Low ThreeMonth_Med ThreeMonth_High
2021-05 NULL NULL NULL NULL
2021-06 NULL NULL NULL NULL
2021-07 53443 23000 21243 9200
2021-08 46622 18800 17954 7168
例如ThreeMonth_TotalMileage 是 2021-05、2021-06、2021-07 所有里程的总和。这只会显示为 2021-07 年的 运行 总数,因为我们有 3 个月的历史记录,我们可以从中计算总和,否则我希望它为空。
3Month_Low 是 2021-05、2021-06、2021-07 的所有低里程总和,基本上包括当前月份加上每个计算的前 2 个。
关于如何尝试使用 SQL 服务器完成此操作的任何想法?谢谢!
您可以使用 Ordered Analytical Function 来实现。思路是求累计和。
要将数据从行旋转到列,您可以使用 CASE
和 MAX
。
select
Month
,Max(case when Type='low' then Mileage end) as Month_Low
,Max(case when Type='med' then Mileage end)as Month_Med
,Max(case when Type='high' then Mileage end) as Month_High
,case when ROW_NUMBER() over(order by Month asc)>=3 Then 1 end as is_3month_data_present
from #demo
group by month
Month | Month_Low | Month_Med | Month_High | is_3month_data_present |
---|---|---|---|---|
2021-05 | 5000 | 6789 | 5000 | null |
2021-06 | 15000 | 12876 | 1500 | null |
2021-07 | 3000 | 1578 | 2700 | 1 |
2021-08 | 3500 | 3500 | 2968 | 1 |
下面的 SQL 应该给出所需的最终结果。
select
Month
,case when is_3month_data_present=1 then Sum(Month_Low+Month_Med+Month_High) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_TotalMileage
,case when is_3month_data_present=1 then Sum(Month_Low) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_Low
,case when is_3month_data_present=1 then Sum(Month_Med ) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_Med
,case when is_3month_data_present=1 then Sum(Month_High) over(order by Month ROWS BETWEEN 2 PRECEDING and CURRENT ROW ) end as ThreeMonth_High
from
(select
Month
,Max(case when Type='low' then Mileage end) as Month_Low
,Max(case when Type='med' then Mileage end)as Month_Med
,Max(case when Type='high' then Mileage end) as Month_High
,case when ROW_NUMBER() over(order by Month asc)>=3 Then 1 end as is_3month_data_present
from #demo
group by Month
)stg
输出:
Month | ThreeMonth_TotalMileage | ThreeMonth_Low | ThreeMonth_Med | ThreeMonth_High |
---|---|---|---|---|
2021-05 | null | null | null | |
2021-06 | null | null | null | |
2021-07 | 53443 | 23000 | 21243 | 9200 |
2021-08 | 46622 | 21500 | 17954 | 7168 |
注意:根据给定的数据集,问题中提供的预期输出是错误的。 ThreeMonth_low 是错误的,其余都是正确的。对于 2021-07,实际值应为 23000
而不是 20300
。
DB Fiddle: Try it here