Oracle 11g合并客户表去重的更优查询方案咨询
更简洁的Oracle 11g客户表合并去重方案
这确实是个很头疼的场景——当字段数量多的时候,重复写MAX() KEEP (DENSE_RANK...)简直是体力活!针对你的需求,我们可以用窗口函数+过滤的方式来简化代码,不管多少字段都只需要一次排序处理就能搞定。
核心思路
- 先用
UNION ALL合并两张表的所有数据,同时标记每条数据的数据源(SAP对应主表,MANUAL对应补充表); - 借助
ROW_NUMBER()窗口函数,以CUSTOMER_NUMBER为分组依据,给每组内的记录按数据源优先级排序(优先保留SAP的记录); - 最后只筛选每组内排序为1的记录,就是去重后的目标结果。
具体SQL实现
SELECT ID, CUSTOMER_NUMBER, NAME, STREET, DATASOURCE FROM ( SELECT ID, CUSTOMER_NUMBER, NAME, STREET, DATASOURCE, -- 按客户编号分组,SAP数据源优先级更高(排序列值越小越先) ROW_NUMBER() OVER ( PARTITION BY CUSTOMER_NUMBER ORDER BY CASE DATASOURCE WHEN 'SAP' THEN 1 ELSE 2 END ) AS rn FROM ( SELECT ID, CUSTOMER_NUMBER, NAME, STREET, 'SAP' AS DATASOURCE FROM CUSTOMERS UNION ALL SELECT ID, CUSTOMER_NUMBER, NAME, STREET, 'MANUAL' AS DATASOURCE FROM CUSTOMERS_MANUAL ) combined ) ranked WHERE rn = 1;
方案优势
- 代码极简:不管你有20个还是更多字段,只需要写一次窗口函数逻辑,不用每个字段都重复
MAX() KEEP的繁琐代码; - 逻辑清晰:通过排序规则明确指定数据优先级,可读性远高于重复的聚合函数;
- 灵活扩展:如果后续需要调整规则(比如要保留
MANUAL表中最新的重复数据),只需要修改ORDER BY的条件即可,比如:ORDER BY CASE DATASOURCE WHEN 'SAP' THEN 1 ELSE 2 END, ID DESC
结果验证
针对你的测试数据,这个查询会返回完全符合期望的结果:
| ID | CUSTOMER_NUMBER | NAME | STREET | DATASOURCE |
|---|---|---|---|---|
| 1 | 4711 | Dirk Downstreet | 4 | SAP |
| 2 | 4721 | Hans Mainstreet | 5 | SAP |
| 4 | 4741 | Harry Crossroad | 9 | MANUAL |
内容的提问来源于stack exchange,提问作者spe92
相关产品推荐
相关产品推荐

