MySQL查询用DISTINCT仍有重复值,GROUP BY加MAX()报错求助
嘿,我懂你现在的困扰——明明加了DISTINCT,结果还是拿到重复的行,试了GROUP BY加MAX()又报错,确实挺闹心的。咱们来一步步拆解问题,找到靠谱的解决办法。
先搞清楚问题根源
你的查询用了旧的逗号分隔关联写法,同时关联了users、mixes、multitracks三个表,很可能出现笛卡尔积的情况:比如一个用户对应3条mixes记录和2条multitracks记录,就会生成3×2=6行结果。而DISTINCT是基于整行所有字段的唯一性判断的,只要某一个字段(比如mixes.id或multitracks.id)不同,整行就会被视为不同的记录,所以DISTINCT根本压不住重复。
至于你用GROUP BY加MAX()报错,大概率是因为MySQL默认开启了ONLY_FULL_GROUP_BY模式,这个模式要求SELECT里的所有非聚合字段必须出现在GROUP BY子句里,或者被聚合函数包裹。你之前可能只给部分字段加了MAX(),或者GROUP BY的字段不全,违反了这个规则,所以才报错。
给你两个实用的解决方案
方案1:先对子表去重,再关联用户表
如果你的需求是每个用户只返回一行(比如对应最新的一条mix和最新的一条multitrack),可以先通过子查询拿到每个用户对应的目标记录,再和users表关联:
SELECT u.firstname, u.lastname, u.id, u.displayname, m.artist, m.title, m.id AS mix_id, mt.artist AS mt_artist, mt.id AS mt_id, mt.title AS mt_title FROM users u -- 关联用户对应的最新mix记录 LEFT JOIN ( SELECT userId, artist, title, id FROM mixes WHERE userId = (SELECT id FROM users WHERE displayname = 'KarriGrl') ORDER BY id DESC LIMIT 1 ) m ON u.id = m.userId -- 关联用户对应的最新multitrack记录(这里需要补充你原查询OR后面的关联条件) LEFT JOIN ( SELECT artist, id, title WHERE /* 这里填multitracks和用户的关联条件,比如 userId = u.id */ ORDER BY id DESC LIMIT 1 ) mt ON /* 补充multitracks和用户/mixes的关联逻辑 */ WHERE u.displayname = 'KarriGrl';
方案2:用UNION ALL拆分关联逻辑,避免笛卡尔积
如果你的需求是展示用户所有的mixes和multitracks记录,但不想让两类记录交叉产生重复行,可以把两个关联查询分开,用UNION ALL合并结果:
-- 查询用户的所有mix记录 SELECT u.firstname, u.lastname, u.id, u.displayname, m.artist, m.title, m.id AS item_id, NULL AS mt_artist, NULL AS mt_id, NULL AS mt_title, 'mix' AS item_type FROM users u JOIN mixes m ON u.id = m.userId WHERE u.displayname = 'KarriGrl' UNION ALL -- 查询用户的所有multitrack记录 SELECT u.firstname, u.lastname, u.id, u.displayname, NULL AS artist, NULL AS title, NULL AS item_id, mt.artist, mt.id, mt.title, 'multitrack' AS item_type FROM users u JOIN multitracks mt ON /* 这里填multitracks和用户的关联条件 */ WHERE u.displayname = 'KarriGrl';
最后提个小建议
一定要先明确你的业务需求:是要每个用户只返回一行数据,还是要展示用户所有关联的mixes和multitracks但不产生交叉重复?另外,把原查询里OR后面的关联条件补充完整,能帮你得到更精准的解决方案哦~
内容的提问来源于stack exchange,提问作者vpereira

