SQL分组文字排序聚合实现

作者:技术拾光

时间:2026-06-13

浏览:590

针对不同数据库实现分组内文字排序聚合功能,列出了Spark、Impala、Oracle、SQLServer、PostgreSQL、MySQL、SQLite、DuckDB、ClickHouse等产品的SQL语法差异,涵盖大数据、商业、开源、嵌入式及分析型数据库,并指出性能受架构影响,大模型时代无需死记硬背。

做数据处理的朋友应该都遇到过这种场景:需要对分组内的文字列做排序聚合,比如按价格高低把每个类别下的商品名字串起来,或者按成绩排好每个班级的学生名单。现在SQL数据库百花齐放,方言差异不小,为了方便查阅,这里整理了一份实测可跑的汇总,覆盖了常见的数据产品与平台。 SQL分组文字排序聚合实现 假设一张销售表 `sales`,要展示每个类别下按价格排序的商品清单。 ```sql CREATE TABLE sales AS SELECT 'Electronics' AS category, 'Laptop' AS product, 1000 AS price UNION ALL SELECT 'Electronics', 'Mouse', 20 UNION ALL SELECT 'Electronics', 'Keyboard', 80 UNION ALL SELECT 'Furniture', 'Desk', 300 UNION ALL SELECT 'Furniture', 'Chair', 150; ``` ## 1. Spark ```sql SELECT category, concat_ws(',', TRANSFORM( SORT_ARRAY(COLLECT_LIST(STRUCT(price, product))), s -> s.product ) ) AS products_sorted FROM sales GROUP BY category; ``` ## 2. Impala ```sql SELECT category, regexp_replace( group_concat(concat_ws('|', rn, product), ','), '[0-9]+\\|', '' ) AS products_sorted FROM ( SELECT category, product, cast(row_number() OVER (PARTITION BY category ORDER BY price) AS STRING) AS rn FROM sales ) t GROUP BY category; ``` ## 3. Oracle ```sql select category, LISTAGG(product, ', ') WITHIN GROUP (ORDER BY price) AS product_sorted from sales t group by category ``` ## 4. SQL Server ```sql SELECT category, STRING_AGG(product, ', ') WITHIN GROUP (ORDER BY price) AS products_sorted FROM sales GROUP BY category; ``` ## 5. PostgreSQL ```sql SELECT category, string_agg(product, ', ' ORDER BY price) AS products_sorted FROM sales GROUP BY category; ``` ## 6. MySQL ```sql SELECT category, GROUP_CONCAT(product ORDER BY price SEPARATOR ',') AS products_sorted FROM sales GROUP BY category; ``` ## 7. SQLite & DuckDB ```sql SELECT category, string_agg(product, ', ' ORDER BY price) AS products_sorted, group_concat(product, ', ' ORDER BY price DESC) AS products_sorted1 FROM sales GROUP BY category; ``` ## 8. ClickHouse ```sql -- 方式一,利用子查询先行排序 SELECT category, arrayStringConcat(groupArray(product), ',') AS products_sorted FROM ( SELECT category, product FROM db_test.sales ORDER BY category, price ASC ) GROUP BY category; -- 方式二,Lambda表达式 SELECT category, arrayStringConcat( arrayMap( x -> x.2, -- 提取元组的第二个元素,即 product arraySort( x -> x.1, -- 按元组的第一个元素(price)升序排序 groupArray((price, product)) ) ), ',' ) AS products_sorted FROM db_test.sales GROUP BY category; ``` ## 总结 从上面的实现可以看出,不同生态的数据库对分组排序聚合的支持思路差异不小。 - **大数据体系**:Spark SQL 需要嵌套 `collect_list` + `sort_array` + `transform` + `concat_ws` 才能实现,逻辑绕,代码长;Impala 不支持在 `group_concat` 内直接 `order by`,得用子查询加 `row_number` 先排好序再正则替换,且只支持 2.3 以上版本。 - **商业数据库**:Oracle 的 `listagg...within group (order by)` 是最早也最经典的实现,后来 SQL Server 2017+ 也提供了 `string_agg...within group (order by)`,格式高度相似,很好记。 - **开源数据库**:PostgreSQL 直接用 `string_agg(expr, sep order by ...)`,MySQL 用 `group_concat(expr order by ... separator sep)`,与商业数据库的格式差异较大,需要额外记一下。 - **嵌入式数据库**:SQLite 和 DuckDB 都支持 `group_concat(expr, sep order by ...)` 或 `string_agg(expr, sep order by ...)`,格式与 PG 高度一致,可见 PG 的影响。SQLite 从 3.44.0 开始才支持带 `order by` 的版本,DuckDB 定位分析型,从最早版本就完整支持。 - **分析型数据库**:ClickHouse 早期相当复杂,要用子查询或 `arrayStringConcat` + `groupArray` + `arraySort` + `arrayMap` 等 Lambda 套路,类似 Spark 的写法;从 24.8 版本起支持 `groupConcat(sep)(expr ORDER BY ...)`,简化了不少,但语法仍保留自家特色。 - **国产信创数据库**:目前主要是兼容模式,比如达梦兼容 Oracle 可跑 `listagg`,海量 Vastbase 原生兼容 PostgreSQL 用 `string_agg`,暂时还没发展出独立的语法体系。 以上只记录了语法差异,实际性能会因为各产品架构设计不同而有较大差距。当然,如果数据量没到亿级,性能基本都能接受。 话说回来,现在大模型时代,死记硬背不同数据库的语法既费时间也没太大必要——只要描述一下场景,大模型直接就能生成完整的 SQL 语句。数据工程师真正需要掌握的是各类产品的特点和背景,这样面对新工具时,就能快速借助 AI 写出复杂逻辑的 SQL 了。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章