MySQL中多列查询但仅对单列去重的问题求助
解决按单一列去重并获取多列数据的问题
嘿,我来帮你搞定这个困扰你的查询问题!你想要查询category、offer_id、store_image三列,但只让category列唯一不重复,之前的两种方法都没达到预期,咱们来一步步拆解问题,找到解决方案。
为什么之前的方法失效了?
先聊聊你踩的两个坑:
- 子查询取最大
offer_id关联后仍有重复category:大概率是你的关联逻辑没过滤到唯一行,或者你的表中存在同一个category下有多行的offer_id等于最大值的情况——这时候关联后自然会返回多行相同的category。 SELECT DISTINCT三列:这个语法是对三列的组合去重,只要任意一列不同就会保留,完全不是你要的“只对category去重”的效果,所以肯定达不到预期。
正确的解决方案
核心思路是:你需要明确告诉数据库,每个category下你要保留哪一行的其他数据(比如最大offer_id对应的行、最新创建的行等),这里推荐两种常用方法:
方法1:用窗口函数ROW_NUMBER()(通用所有支持窗口函数的数据库:MySQL 8+、PostgreSQL、SQL Server等)
这是最通用的方案,逻辑清晰,适合所有主流数据库:
-- 先给每个category下的行排序,标记序号 WITH ranked_offers AS ( SELECT category, offer_id, store_image, -- 按category分组,组内按offer_id降序排序,第一行标记为1 ROW_NUMBER() OVER (PARTITION BY category ORDER BY offer_id DESC) AS row_num FROM your_table_name -- 替换成你的表名 ) -- 只取每个category的第一行 SELECT category, offer_id, store_image FROM ranked_offers WHERE row_num = 1;
如果你的需求不是取最大的offer_id,而是其他规则(比如最新的store_image、最早创建的offer),只需要修改ORDER BY后面的字段就行,比如ORDER BY created_at DESC。
方法2:用PostgreSQL的DISTINCT ON语法(仅PostgreSQL可用)
如果你用的是PostgreSQL,这个语法会更简洁:
SELECT DISTINCT ON (category) category, offer_id, store_image FROM your_table_name -- 替换成你的表名 -- 必须先按category排序,再按你想要的规则排序(比如取最大offer_id) ORDER BY category, offer_id DESC;
DISTINCT ON (category)会直接保留每个category的第一行,后面的ORDER BY用来指定每个组内哪一行是“第一行”。
补坑:修复你之前的子查询方法
如果你还是想用子查询的方式,需要确保关联后只取唯一行,比如:
SELECT t.category, t.offer_id, t.store_image FROM your_table_name t INNER JOIN ( -- 先获取每个category的最大offer_id SELECT category, MAX(offer_id) AS max_offer_id FROM your_table_name GROUP BY category ) t_max ON t.category = t_max.category AND t.offer_id = t_max.max_offer_id -- 如果同一个category下有多个行等于max_offer_id,加这一行确保只取一个 QUALIFY ROW_NUMBER() OVER (PARTITION BY t.category ORDER BY t.offer_id DESC) = 1;
不过这种方法不如窗口函数直观,还是推荐第一种方案。
内容的提问来源于stack exchange,提问作者Samir Sheikh
相关产品推荐
相关产品推荐

