使用LISTAGG处理VARCHAR数据时,Partition与Group By哪种更高效?
关于LISTAGG两种写法的效率对比及场景分析
首先得明确:这两种写法本质返回的结果完全不同,这是分析效率的核心前提:
- 写法一(GROUP BY聚合):按
department_id分组,每个部门仅返回一行结果,对应该部门的员工列表 - 写法二(窗口函数):返回每一条员工记录,且每条记录都附带其所在部门的员工列表,结果行数等于员工总数
效率对比
如果你的需求是获取每个部门一行的聚合结果,写法一的效率会显著更高:
- 计算量:写法一仅对每个部门做一次LISTAGG聚合;写法二需要为每一条员工记录重复计算所在部门的员工列表,冗余计算量极大
- 数据传输:写法一返回行数是部门数量,写法二是员工总数,后者的数据量要大得多,对网络、存储的消耗也更明显
如果你的需求是保留每条员工的原始数据,同时附带所在部门的员工列表,那写法二是唯一适配的选择,这时就不用纠结效率——需求本身决定了必须用窗口函数实现。
关于你的使用习惯
你提到“除非仅选择1-2列,否则总会用Partition,因为无需将每个列都加入GROUP BY子句”,这个习惯要结合需求场景调整:
- 如果最终需要的是聚合后的分组结果,哪怕要选多列,也应该用GROUP BY(把需要展示的非聚合列加入GROUP BY,或用聚合函数处理),避免用窗口函数后再去重,那样反而会额外增加开销
- 如果需要每条原始记录都附带聚合信息,窗口函数确实更便捷,不用额外处理分组逻辑
两种写法的代码示例
写法一(GROUP BY聚合):
SELECT department_id AS "Dept.", LISTAGG(last_name, '; ') WITHIN GROUP (ORDER BY hire_date) AS "Employees" FROM employees GROUP BY department_id ORDER BY department_id;
写法二(窗口函数):
SELECT department_id AS "Dept.", LISTAGG(last_name, '; ') WITHIN GROUP (ORDER BY hire_date) OVER (PARTITION BY department_id) AS "Employees" FROM employees ORDER BY department_id;
内容的提问来源于stack exchange,提问作者AJQShake
相关产品推荐
相关产品推荐

