INNER JOIN查询如何有效消除结果集中的冗余条目
冗余问题的本质
当前结果中出现stipend重复的根源,是moniker_tbl和student_tbl的关联关系是 一对多:同一个学生姓名(name字段)在moniker_tbl中对应多条昵称记录,和student_tbl里单条助学金记录匹配后,自然会生成多份带着相同stipend的冗余条目。
避坑提醒:直接在原JOIN查询的结果上套
DISTINCT完全达不到效果——不同的昵称本身就是不同的行内容,DISTINCT会把所有nickname+stipend的组合都保留,根本没法实现 每个学生只展示一条关联昵称 的需求。
可行的解决思路
核心是从关联的源头做去重:先对moniker_tbl按关联键(name字段)做筛选,每个name只保留1条需要展示的昵称,再和student_tbl做内连接,彻底切断多对一的关联冗余。
通用兼容方案(支持所有MySQL版本)
通过子查询对moniker_tbl按name分组聚合,每个name取出一条目标昵称后再关联:
SELECT t1.nickname, t2.stipend FROM -- 先按name聚合,每个name只留一条昵称 (SELECT name, MIN(nickname) AS nickname FROM moniker_tbl GROUP BY name) AS t1 INNER JOIN student_tbl AS t2 ON t1.name = t2.name;
这里用MIN(nickname)是取每个name下字典序最靠前的昵称,刚好匹配示例中选中"Jonny"作为John Doe对应昵称的预期输出。
如果需要自定义选取的昵称规则(比如取最新插入的那条记录对应的昵称),可以把聚合逻辑换成关联子查询实现:
SELECT t1.nickname, t2.stipend FROM (SELECT name, nickname FROM moniker_tbl m1 -- 取每个name下id最大的那条记录(也就是最新插入的) WHERE id = (SELECT MAX(id) FROM moniker_tbl m2 WHERE m2.name = m1.name)) AS t1 INNER JOIN student_tbl AS t2 ON t1.name = t2.name;
MySQL 8.0+ 优化方案
如果用的是支持窗口函数的数据库版本,可以用分区排序的方式筛选每个name下的第一条记录,执行效率比逐行关联子查询更高:
SELECT t1.nickname, t2.stipend FROM (SELECT name, nickname, -- 按name分区,按id升序排序,每个分区的第一行标记rn=1 ROW_NUMBER() OVER (PARTITION BY name ORDER BY id ASC) AS rn FROM moniker_tbl ) AS t1 INNER JOIN student_tbl AS t2 ON t1.name = t2.name WHERE t1.rn = 1;
内容的提问来源于stack exchange,提问作者Sandeep
相关产品推荐
相关产品推荐

