如何选择唯一ID并优先指定列值?数据库查询去重求助
解决思路:避免Union重复,用优先级排序或精准过滤
首先得说为啥你用Union会出现重复ID——因为你可能直接把「有good记录的ID的目标行」和「所有ID的最早行」拼在一起了,那些有good的ID会在两个结果集里都出现,自然就重复了。
给你两个靠谱的解决方向:
方向1:用窗口函数(推荐,简洁高效)
这是最优雅的方式,给每个ID的行按规则排优先级,然后只取每个ID的第一行。比如用ROW_NUMBER()窗口函数:
WITH ranked_data AS ( SELECT ID, Date, Result, -- 先给行排优先级:good的行优先,然后在同优先级里按Date排序(按你的例子取最大的Date,要最早的就把DESC改成ASC) ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY CASE WHEN Result = 'good' THEN 1 ELSE 2 END, Date DESC ) AS row_rank FROM your_table_name ) SELECT ID, Date, Result FROM ranked_data WHERE row_rank = 1;
逻辑解释:
PARTITION BY ID:把数据按ID分组,每个ID单独处理ORDER BY的第一个条件:把Result为good的行标记为优先级1,其他为2,确保good的行排在最前面- 第二个条件:在同一优先级里,按Date排序(你的例子里取了ID1的good行中Date更大的12,所以用DESC;如果要最早的Date就用ASC)
- 最后取每个ID里
row_rank=1的行,就是符合要求的唯一ID结果。
方向2:修正Union的过滤逻辑(如果你坚持用Union)
问题出在Union的第二个结果集没有排除已经在第一个集里的ID,所以要加个判断,确保第二个集只包含没有good记录的ID:
-- 第一部分:有good记录的ID,取其good行中目标Date的行 SELECT ID, Date, Result FROM your_table_name t1 WHERE Result = 'good' AND Date = (SELECT MAX(Date) FROM your_table_name t2 WHERE t2.ID = t1.ID AND t2.Result = 'good') UNION -- 第二部分:没有good记录的ID,取其最早Date的行 SELECT ID, Date, Result FROM your_table_name t1 WHERE NOT EXISTS (SELECT 1 FROM your_table_name t2 WHERE t2.ID = t1.ID AND t2.Result = 'good') AND Date = (SELECT MIN(Date) FROM your_table_name t2 WHERE t2.ID = t1.ID);
这样两个结果集的ID完全不重叠,Union后就不会有重复了。
补充说明
如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用子查询的方式(类似上面Union里的逻辑,不过写起来繁琐点),但窗口函数的方法无论是可读性还是性能都更好,优先推荐。
内容的提问来源于stack exchange,提问作者Edi Itelman
相关产品推荐
相关产品推荐

