繁体   English   中英

获取动态创建的数据透视表的行总计

[英]Get Row Totals for Dynamically Created Pivoted Table

在 PostgreSQL 中,我有一个这样的表:

CREATE TABLE cross_table (brand varchar(10), gender varchar(10), sales int);

INSERT INTO cross_table (brand, gender, sales) VALUES ('Nike', 'Male', 10);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Nike', 'Male', 20);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Adidas', 'Woman', 20);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Nike', 'Male', 10);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Adidas', 'Woman', 30);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Puma', 'Woman', 40);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Puma', 'Male', 10);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Nike', 'Male', 20);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Puma', 'Woman', 10);
INSERT INTO cross_table (brand, gender, sales) VALUES ('Adidas', 'Woman', 20);

然后我运行此查询以将品牌作为行,将性别作为列并将销售额作为值:

with main_query as (    
    SELECT  brand,
            GROUPING(brand) AS "brand_grouping",
            gender,
            GROUPING(gender) AS "gender_grouping",
            sum(sales) AS "sales"
    FROM    cross_table
    GROUP BY ROLLUP (brand, gender)
),  
second_query AS (
    SELECT  brand,
            brand_grouping,
            cast(
                json_object_agg(
                  gender,
                  sales
                  ORDER BY gender DESC
                ) FILTER (WHERE gender_grouping = 0) AS jsonb) "gender",
            SUM(sales)  AS "sales"
    FROM main_query
    GROUP BY (brand, brand_grouping)
)

SELECT  brand,
        gender,
        sales
FROM    second_query
ORDER BY brand_grouping, brand

这将产生以下结果:

品牌 性别 销售量
阿迪达斯 { “女人”:70 } 140
耐克 “男”:60 120
彪马 “男”:10,“女”:50 120
NULL NULL 190

请注意:性别列现在位于 object 中,但括号不会显示在 Stackoverflow 上的表格视图中。

这很好,唯一的问题是它缺少透视“性别”列的行总计。 我可以通过将最后一个查询更改为此来解决这个硬编码:

SELECT  brand,
        CASE WHEN gender IS null THEN
            jsonb_build_object(
                'Woman', SUM(("gender"->>'Woman')::float8) OVER (),
                'Male', SUM(("gender"->>'Male')::float8) OVER ()
        ) ELSE "gender" END AS "gender",
        sales
FROM    second_query
ORDER BY brand_grouping, brand

得到这个结果:

品牌 性别 销售量
阿迪达斯 {“女人”:70} 140
耐克 “男”:60 120
彪马 “男”:10,“女”:50 120
NULL “男”:70,“女”:120 190

这是正确的,但我需要在不知道“性别”的键(男/女)的情况下动态地执行此操作。

有谁知道如何做到这一点?

尝试这个:

SELECT brand
     , jsonb_object_agg(gender, sales) AS gender
     , sum(sales) AS sales
  FROM (
SELECT brand
     , gender
     , sum(sales) AS sales
  FROM cross_table
 GROUP BY ROLLUP(brand), gender
) AS a
GROUP BY brand

结果:

品牌 性别 销售量
null {“男”:70,“女”:120} 190
阿迪达斯 {“女人”:70} 70
耐克 {“男”:60} 60
彪马 {“男”:10,“女”:50} 60

dbfiddle

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM