如何用PL SQL实现类似Pandas分组去空去重并生成列表的功能?
PL/SQL实现分组去空去重并生成列表结果
需求说明
实现与你提供的Pandas代码一致的逻辑:对数据分组后,去除分组内的NULL值、删除重复值,最终返回结果规则为:
- 分组内无有效非空数据时返回NULL
- 分组内仅1条唯一非空数据时返回该值
- 分组内有多条唯一非空数据时返回列表/集合
实现方案
1. 定义全局集合类型(用于存储多值结果)
如果需要返回数组形式的列表,首先在SQL层创建自定义集合类型(根据目标字段类型调整,这里以VARCHAR2为例):
CREATE OR REPLACE TYPE VARCHAR2_LIST AS TABLE OF VARCHAR2(4000); /
如果目标字段是数字类型,可改为:
CREATE OR REPLACE TYPE NUMBER_LIST AS TABLE OF NUMBER; /
2. 分组查询实现逻辑
假设你的表名为tmp,分组字段为group_col1, group_col2(支持单字段或多字段),目标处理字段为target_col,以下是兼容Oracle 12c+的实现:
SELECT group_col1, group_col2, CASE -- 无有效非空数据时返回NULL WHEN COUNT(DISTINCT target_col) FILTER (WHERE target_col IS NOT NULL) = 0 THEN NULL -- 仅1条唯一非空数据时返回该值 WHEN COUNT(DISTINCT target_col) FILTER (WHERE target_col IS NOT NULL) = 1 THEN MAX(target_col) FILTER (WHERE target_col IS NOT NULL) -- 多条唯一非空数据时返回集合列表 ELSE CAST(COLLECT(DISTINCT target_col ORDER BY target_col) AS VARCHAR2_LIST) END AS result_list FROM tmp GROUP BY group_col1, group_col2;
如果你的Oracle版本低于12c(不支持FILTER子句),可改用CASE嵌套实现过滤:
SELECT group_col1, group_col2, CASE WHEN COUNT(DISTINCT CASE WHEN target_col IS NOT NULL THEN target_col END) = 0 THEN NULL WHEN COUNT(DISTINCT CASE WHEN target_col IS NOT NULL THEN target_col END) = 1 THEN MAX(CASE WHEN target_col IS NOT NULL THEN target_col END) ELSE CAST(COLLECT(DISTINCT CASE WHEN target_col IS NOT NULL THEN target_col END ORDER BY target_col) AS VARCHAR2_LIST) END AS result_list FROM tmp GROUP BY group_col1, group_col2;
3. 可选:返回逗号分隔的字符串列表
如果不需要集合类型,而是需要字符串形式的列表(如值1, 值2, 值3),可使用LISTAGG函数:
SELECT group_col1, group_col2, CASE WHEN COUNT(DISTINCT CASE WHEN target_col IS NOT NULL THEN target_col END) = 0 THEN NULL WHEN COUNT(DISTINCT CASE WHEN target_col IS NOT NULL THEN target_col END) = 1 THEN MAX(CASE WHEN target_col IS NOT NULL THEN target_col END) ELSE LISTAGG(DISTINCT target_col, ', ') WITHIN GROUP (ORDER BY target_col) END AS result_string FROM tmp GROUP BY group_col1, group_col2;
内容的提问来源于stack exchange,提问作者Любовь Пономарева
相关产品推荐
相关产品推荐

