SQL:去重的几种常用方法(oracle)

嘿,小伙伴们,说到Oracle数据库里的去重技巧,其实也就那么几种。
比如说,用DISTINCT关键字来去重,这可是SQL里最基础的招数,直接就能帮你干掉那些重复的行。
不过,这法子有个小限制,就是只能对付那些你想去重的字段,要是你想展示其他信息,就得另想办法了。

再来,GROUP BY也是去重的好帮手,尤其是当你面对多个字段需要去重的时候。
它不仅能帮你筛选出每组唯一的记录,还能让你在保留字段上发挥创意,还能和那些聚合函数一起嗨皮。

窗口函数去重,听起来有点高大上,其实就是用来标记重复数据,然后挑出那些独一无二的数据行。
这招的好处是,你可以玩转各种复杂的去重逻辑,比如按特定顺序来去重。

IN+ROWID去重,这招适用于那些有唯一标识字段的表格,通过比较这些标识来去重。
不过,这招得在标识字段是唯一的情况下才管用。

NOT EXISTS去重,这招是通过子查询来判断数据是否重复,只选出那些不重复的宝贝。
这法子逻辑清晰,简单易懂,适合那些复杂的查询场景。

INNER JOIN + GROUP BY去重,这招结合了内连接和分组操作,让你在两个或多个表之间轻松去重。
这可是跨表去重的神器,灵活性十足。

总之,每种去重方法都有它的独门绝技,关键是要根据你的具体需求来挑选最合适的那个。
小伙伴们,你们学会了吗?

如何使用 SQL 查询去除 LEFT JOIN 中产生的重复记录?

在写SQL查询的时候,咱们有时候用LEFT JOIN会遇到点烦心事,就是关联表里如果有多条匹配的记录,结果集就可能出现重复。
别担心,这儿有几个方法可以帮你搞定这个问题。

方法1 :子查询+聚合函数(推荐) 这个方法挺常用的。
你可以先在子查询里对b表按关联字段(比如sid)分组,然后用聚合函数比如MAX提取每组里的一条记录(比如最大的跟踪号),最后再跟a表连接起来。
比如这样: sql SELECT a. FROM a LEFT JOIN ( SELECT sid, MAX(tracking_number) AS tracking_number FROM b GROUP BY sid ) b ON a.sid = b.sid;
这里子查询通过GROUP BY sid和MAX(tracking_number)确保每个sid只返回一条记录。
这个方法适用于你想要保留b表中某个字段(比如最新跟踪号)的场景。

方法2 :窗口函数(适用于支持窗口函数的数据库) 如果你的数据库支持窗口函数(像PostgreSQL、SQLServer、MySQL 8 .0+这些),你可以用ROW_NUMBER()给每组里的记录标个号。
比如: sql WITH ranked_b AS ( SELECT b., ROW_NUMBER() OVER (PARTITION BY sid ORDER BY id DESC) AS rn FROM b ) SELECT a., rb.tracking_number FROM a LEFT JOIN ranked_b rb ON a.sid = rb.sid AND rb.rn = 1 ;
这里PARTITION BY sid按sid分组,ORDER BY id DESC确保取每组中id最大的记录。
然后通过rn=1 过滤,就只保留每组的第一条记录了。

方法3 :DISTINCT或GROUP BY去重 如果你只需要a表的唯一记录,而且不关心b表的重复关联,可以直接对结果去重。
比如: sql SELECT DISTINCT a. FROM a LEFT JOIN b ON a.sid = b.sid;
或者按a表的主键分组: sql SELECT a. FROM a LEFT JOIN b ON a.sid = b.sid GROUP BY a.id; -
假设a.id是主键
不过要注意,这个方法会丢掉b表的重复关联信息,只保留a表的唯一记录。

方法4 :EXISTS替代LEFT JOIN 如果你只是想判断b表中是否存在匹配记录,不需要关心具体内容,可以用EXISTS来避免重复。
比如: sql SELECT a., CASE WHEN EXISTS (SELECT 1 FROM b WHERE b.sid = a.sid) THEN 1 ELSE 0 END AS has_match FROM a;
这个方法通过EXISTS判断b表中是否存在匹配的sid,返回1 或0表示是否存在匹配。

关键点总结 明确需求:你想保留b表中的特定记录(比如最新记录),还是只需判断关联是否存在? 数据库兼容性:简单的聚合函数(如MAX)适用于大多数数据库,但窗口函数需要较新版本的数据库支持。
性能考虑:子查询或窗口函数可能会影响性能,尤其是在大数据量时,建议测试一下执行计划。

示例场景 假设a表是订单,b表是订单跟踪记录,你想查询订单及其最新跟踪号,可以用方法1 的变体: sql SELECT a.order_id, a.order_date, b_latest.tracking_number FROM a LEFT JOIN ( SELECT sid, MAX(tracking_number) AS tracking_number FROM b GROUP BY sid ) b_latest ON a.sid = b_latest.sid;
这样就能有效避免LEFT JOIN导致的重复记录问题了。