【问题标题】:Get ROLLUP to include rows for missing values获取 ROLLUP 以包含缺失值的行
【发布时间】:2025-12-23 13:45:06
【问题描述】:

PostgreSQL 14

假设这个样本数据:

fruit ripeness
orange 1
orange 3
apple 0
apple 3
apple 3
apple 2

有没有办法让 ROLLUP 给我一个按成熟度计算的水果数量,并为每个可能的成熟度值设置一行,如下所示:

fruit ripeness count
orange 0 0
orange 1 1
orange 2 0
orange 3 1
orange 2
apple 0 1
apple 1 0
apple 2 1
apple 3 2
apple 4
6

而不仅仅是组中的现有值如下所示:

fruit ripeness count
orange 1 1
orange 3 1
orange 2
apple 0 1
apple 2 1
apple 3 2
apple 4
6

【问题讨论】:

    标签: postgresql group-by left-join rollup cross-join


    【解决方案1】:

    fruit 的不同值交叉连接到ripeness 的不同值,并将LEFT 连接到表。
    然后与ROLLUP聚合:

    SELECT f.fruit, r.ripeness, 
           COUNT(t.fruit) counter
    FROM (SELECT DISTINCT fruit FROM tablename) f
    CROSS JOIN (SELECT DISTINCT ripeness FROM tablename) r
    LEFT JOIN tablename t ON t.fruit = f.fruit AND t.ripeness = r.ripeness
    GROUP BY ROLLUP(f.fruit, r.ripeness)
    ORDER BY f.fruit, r.ripeness;
    

    请参阅demo

    【讨论】:

    • 那行得通。如果我有三个组,即水果、成熟度、质量,它会变得多丑?
    • @EMF 为此,您需要另一个具有不同品质的交叉连接。
    【解决方案2】:

    没有ROLLUP的解决方案,幼稚但直观:

    select * from (
      (
        select distinct f1.fruit, f2.ripeness, (
            select count(1) from fruit fsq where
                f1.fruit = fsq.fruit and
                f2.ripeness = fsq.ripeness
        ) from fruit f1
        left join fruit f2 on true
        group by f1.fruit, f2.ripeness
      )
      union
      (
      select fruit.fruit, null, count(1) from fruit
        group by fruit.fruit
      )
      union
      (
      select null, null, count(1) from fruit
      )
    ) mq
    order by 1, 2;
    

    Demo.

    【讨论】:

    • 由于简化示例中未显示的原因,我需要使用 ROLLUP
    最近更新 更多