PostgreSQL多字段过滤后仅按单个字段分组的查询实现问题
SQL分组查询问题解决方案
问题前提
涉及数据表:sales

原有正常查询(按所有非聚合选取字段分组)
SELECT brand, SUM (total) FROM sales GROUP BY brand;
需求&错误写法
需要同时按brand和segment两个字段过滤数据,最终仅按brand单个字段分组,以下写法不符合语法规则会报错:
SELECT brand, segment, SUM (total) FROM sales GROUP BY brand;
报错原因
SQL标准GROUP BY语法强制要求:所有没有被聚合函数包裹的查询字段,必须全部出现在GROUP BY的分组字段列表中,上述查询中segment字段既没有用聚合函数包裹,也没有加入GROUP BY列表,因此无法运行。
不同场景下的解决方案
场景1:仅需要按brand分组求和,不需要在结果中展示segment取值
直接在WHERE子句中加segment的过滤条件即可:
SELECT brand, SUM(total) AS brand_total FROM sales -- 此处添加segment过滤规则,支持等于、IN、范围匹配等逻辑 WHERE segment IN ('要筛选的segment值1', '要筛选的segment值2') -- 也可以加brand的过滤条件,比如 AND brand = 'xxx' GROUP BY brand;
场景2:需要在结果中展示当前品牌关联的所有segment取值,同时按brand分组求和
用字符串聚合函数包裹segment字段即可,不同数据库的聚合函数有差异,示例如下:
MySQL写法
SELECT brand, GROUP_CONCAT(DISTINCT segment SEPARATOR ',') AS related_segments, SUM(total) AS brand_total FROM sales WHERE 自定义过滤条件 GROUP BY brand;
SQL Server写法
SELECT brand, STRING_AGG(DISTINCT segment, ',') AS related_segments, SUM(total) AS brand_total FROM sales WHERE 自定义过滤条件 GROUP BY brand;
Oracle写法
SELECT brand, LISTAGG(DISTINCT segment, ',') WITHIN GROUP (ORDER BY segment) AS related_segments, SUM(total) AS brand_total FROM sales WHERE 自定义过滤条件 GROUP BY brand;
场景3:需要同时展示单品牌单segment的销售额、以及对应品牌的总销售额
用窗口函数实现即可,不需要GROUP BY:
SELECT DISTINCT brand, segment, SUM(total) OVER(PARTITION BY brand, segment) AS segment_sales, SUM(total) OVER(PARTITION BY brand) AS brand_total_sales FROM sales WHERE 自定义过滤条件
内容的提问来源于stack exchange,提问作者Mbanda
相关产品推荐
相关产品推荐

