select 的 MODEL 子句在结果集上添加列,而不仅仅是新行?

问题描述 投票:0回答:2

PIVOT 只能将一个值转入其一列。 此外,如果例如我们想要旋转和(分组)值的相交范围,则 PIVOT 也没有帮助。

因此我们计划使用 MODEL 子句来克服这个限制。

我们必须转向专栏:

  • sum()、count() 过去 2 年各个季度的数据以及 将每个季度的结果呈现在自己的一组列中;
  • sum()、count() 计算过去 2 年中不同年份的数据,并将每年的结果呈现到自己的一组列中;
  • sum()、count() 计算过去 3 个月内各个月份的数据,并将每个月的结果呈现到自己的一组列中。

分桶中的季度/年/月列表是固定的,可以在 MODEL 子句中进行硬编码(即始终会回顾 2 年)。

我有一个工作原型,使用三个独立的枢轴进行上述操作,但效率非常低,因为每个枢轴都必须再次传递我们庞大的数据集。

我们预计 MODEL 可能只需要对数据集进行一次传递。

问题:

  • MODEL 子句是否可以创建新列(即我们分组
    按子查询中的月份和产品类别,但 MODEL 应该添加
    上述季度/年/月的列)?
  • 无法想出定义维度和度量的最佳方法,因此我们可以 创建新专栏..任何想法都将受到高度赞赏。

编辑:在 https://community.oracle.com/message/13951429

发布了同样的问题
sql oracle pivot
2个回答
1
投票

您可以使用多个数据透视列和多个结果列进行透视

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
         )
   )

0
投票

看看另一个方向,其想法是预先计算您想要报告的所有期间及其开始结束日期,然后只需与原始数据连接即可:

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”...

© www.soinside.com 2019 - 2024. All rights reserved.