Oracle PIVOT - 未使用的列影响汇总

Oracle PIVOT - unused columns affect rollup

我有一个数据集,其中包含几个关键字段、一个状态和一个计数。 PIVOT 做得很好,每个关键字段组合一行,每个状态一列。示例如下:

with dataquery (field1, field2, field3, my_status, statcount) as (
select 'AAA', 'BBB', 'CCC', 'XX', 11 from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 22 from dual
union
select 'AAA', 'BBB', 'CCC', 'ZZ', 33 from dual
), 
pivotquery as (
 SELECT field1,
    field2,
    field3,
    xx_stat_count     AS xx,
    yy_stat_count     AS yy,
    zz_stat_count     AS zz
  FROM dataquery
    PIVOT (
        SUM (statcount) AS stat_count
        FOR (my_status)
        IN ('XX' AS XX,
            'YY' AS yy,
            'ZZ' AS zz
            )
          )
)
select * from pivotquery;

这给出了预期的结果:

FIELD1   FIELD2  FIELD3  XX  YY  ZZ
AAA      BBB     CCC     11  22  33

但是,如果我在数据中有额外的列,它不会忽略它们并按照我的预期汇总。它似乎试图将未使用的列用作分组逻辑的一部分,而不是忽略它们。如果我将输入更改为:

with dataquery (field1, field2, field3, my_status, statcount, cnt2, cnt3, cnt4) as (
select 'AAA', 'BBB', 'CCC', 'XX', 11, 12, 13, 14 as cnt4 from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 22, 22, 23, 24 as cnt4  from dual
union
select 'AAA', 'BBB', 'CCC', 'ZZ', 33, 32, 33, 34 as cnt4  from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 122, 32, 33, 34 as cnt4  from dual
)

我明白了:

FIELD1 FIELD2 FIELD3  XX  YY   ZZ
AAA    BBB    CCC         22
AAA    BBB    CCC         122  33
AAA    BBB    CCC     11

而不是预期的

FIELD1 FIELD2 FIELD3  XX  YY   ZZ
AAA    BBB    CCC     11  144  33

如果我进一步更改输入数据,那么其他字段就不会重复,它会显示为 4 行:

with dataquery (field1, field2, field3, my_status, statcount, cnt2, cnt3, cnt4) as (
select 'AAA', 'BBB', 'CCC', 'XX', 11, 12, 13, 14 as cnt4 from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 22, 22, 23, 24 as cnt4  from dual
union
select 'AAA', 'BBB', 'CCC', 'ZZ', 33, 32, 33, 34 as cnt4  from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 122, 132, 33, 34 as cnt4  from dual
)

给予

FIELD1 FIELD2 FIELD3  XX  YY   ZZ
AAA    BBB    CCC         22
AAA    BBB    CCC              33
AAA    BBB    CCC         122  
AAA    BBB    CCC     11

这是预期的行为吗?

我可以解决这个问题,方法是预先添加一个子查询 select 只是要由 PIVOT 处理的 field1、field2、field3、mystatus 和 statcount,或者执行 select /之后分组,得到卷起来。

Is this expected behavior?

是的,来自 SELECT documentation:

The pivot_clause computes the aggregation functions specified at the beginning of the clause. Aggregation functions must specify a GROUP BY clause to return multiple values, yet the pivot_clause does not contain an explicit GROUP BY clause. Instead, the pivot_clause performs an implicit GROUP BY. The implicit grouping is based on all the columns not referred to in the pivot_clause, along with the set of values specified in the pivot_in_clause.). If you specify more than one aggregation function, then you must provide aliases for at least all but one of the aggregation functions.


要解决它,请使用子查询仅 SELECT 所需的列,以便其他列不会隐式用作 GROUP BY 子句:

with dataquery (field1, field2, field3, my_status, statcount, cnt2, cnt3, cnt4) as (
select 'AAA', 'BBB', 'CCC', 'XX', 11, 12, 13, 14 as cnt4 from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 22, 22, 23, 24 as cnt4  from dual
union
select 'AAA', 'BBB', 'CCC', 'ZZ', 33, 32, 33, 34 as cnt4  from dual
union
select 'AAA', 'BBB', 'CCC', 'YY', 122, 132, 33, 34 as cnt4  from dual
)
SELECT field1,
       field2,
       field3,
       xx_stat_count     AS xx,
       yy_stat_count     AS yy,
       zz_stat_count     AS zz
FROM   (
 SELECT field1,
        field2,
        field3,
        my_status,
        statcount
 FROM   dataquery
)
PIVOT (
  SUM (statcount) AS stat_count
  FOR (my_status) IN (
    'XX' AS XX,
    'YY' AS yy,
    'ZZ' AS zz
  )
);

输出:

FIELD1 FIELD2 FIELD3 XX YY ZZ
AAA BBB CCC 11 144 33

db<>fiddle here