PIVOT 只能将一个值转入其一列。 此外,如果例如我们想要旋转和(分组)值的相交范围,则 PIVOT 也没有帮助。
因此我们计划使用 MODEL 子句来克服这个限制。
我们必须转向专栏:
分桶中的季度/年/月列表是固定的,可以在 MODEL 子句中进行硬编码(即始终会回顾 2 年)。
我有一个工作原型,使用三个独立的枢轴进行上述操作,但效率非常低,因为每个枢轴都必须再次传递我们庞大的数据集。
我们预计 MODEL 可能只需要对数据集进行一次传递。
问题:
您可以使用多个数据透视列和多个结果列进行透视
with atc as
(select owner, table_name, column_name, data_type, nullable
from all_tab_columns
where table_name = 'ALL_TAB_COLUMNS')
select *
from atc
pivot
(max(column_name) as max_col_name, min(column_name) as min_col_name
for (data_type, nullable) in
(
('NUMBER','N') as dt_number_n, ('VARCHAR2','N') as dt_vc_n,
('NUMBER','Y') as dt_number_y, ('VARCHAR2','Y') as dt_vc_y
)
)
看看另一个方向,其想法是预先计算您想要报告的所有期间及其开始结束日期,然后只需与原始数据连接即可:
with data(dat, kind, value) as (
select date '2023-01-01', 'A', 10 union all
select date '2023-01-01', 'B', 11 union all
select date '2023-01-01', 'C', 12 union all
select date '2023-02-01', 'A', 20 union all
select date '2023-02-01', 'B', 21 union all
select date '2023-02-01', 'C', 22 union all
select date '2023-05-01', 'A', 33 union all
select date '2024-05-01', 'A', 110 union all
select date '2024-05-01', 'B', 111 union all
select date '2024-06-01', 'C', 112 union all
select date '2024-06-01', 'A', 120 union all
select date '2024-07-01', 'B', 121 union all
select date '2024-07-01', 'C', 122 union all
select date '2024-08-01', 'A', 133 -- union all
)
, periods(rn, idx, year, factor, from_dat, to_dat, name) as (
select rn, idx, year, factor,
ADD_MONTHS(trunc(to_date(year, 'YYYY'),'YEAR'),factor*(idx-1)),
ADD_MONTHS(trunc(to_date(year, 'YYYY'),'YEAR'),factor*idx) - 1,
name
from (
select level as rn, mod(level-1,12)+1 as idx,
extract(year from sysdate) - 1 + case when level <= 12 then 0 else 1 end as year,
1 as factor,
'MONTH ' || (mod(level-1,12)+1) as name
connect by level <= 24
union all
select level + 24, mod(level-1,3)+1 ,
extract(year from sysdate) - 1 + case when level <= 3 then 0 else 1 end,
4,
'QUARTER ' || (mod(level-1,3)+1)
connect by level <= 6
union all
select level + 24 + 6, 1, extract(year from sysdate) - 2 + level,
12,
'YEAR'
connect by level <= 2
)
)
select * from (
select year, kind, name, sum(value) as s, count(value) as c
from (
select d.*, p.year, p.rn, p.factor, p.name
from
data d
join periods p on d.dat between p.from_dat and p.to_dat
)
group by year, kind, factor, name
)
pivot (
max(s) as sum, max(c) as count for kind in (
'A' as ka, 'B' as kb, 'C' as kc
)
)
;
注意是用 23ai 完成的,所以你可能需要添加一些“FROM DUAL”...