游戏数据库多表INNER JOIN查询时如何排除重复数据
嘿,这个问题我做游戏数据查询的时候也碰到过!核心原因很简单——你关联的是一对多关系的表(一款游戏对应多种类型、多个角色),INNER JOIN会把每种类型和每个角色的组合都枚举出来,自然就导致基础数据重复泛滥了。下面给你几个实用的解决思路,适配不同的场景:
方法1:用DISTINCT快速去重(适合只取基础数据的场景)
如果你的查询只需要game_data_primary里的核心字段,直接在SELECT后加DISTINCT就能过滤掉完全重复的行:
SELECT DISTINCT gdp.* FROM game_data_primary gdp INNER JOIN game_genre gg ON gdp.game_id = gg.game_id INNER JOIN game_cast gc ON gdp.game_id = gc.game_id WHERE gdp.game_id = 123;
⚠️ 注意:如果查询里包含类型或角色字段,DISTINCT就起不到作用了——因为不同的类型/角色会让整行数据变得唯一。
方法2:分组聚合合并多值(完美适配详情页展示)
游戏详情页通常需要同时展示基础数据+所有关联类型/角色,这时候用GROUP BY把基础数据分组,再用聚合函数把多值合并成逗号分隔的列表(不同数据库函数略有差异):
MySQL示例:
SELECT gdp.game_id, gdp.release_year, gdp.developer, GROUP_CONCAT(DISTINCT gg.genre_name SEPARATOR ', ') AS game_genres, GROUP_CONCAT(DISTINCT gc.character_name SEPARATOR ', ') AS game_characters FROM game_data_primary gdp INNER JOIN game_genre gg ON gdp.game_id = gg.game_id INNER JOIN game_cast gc ON gdp.game_id = gc.game_id WHERE gdp.game_id = 123 GROUP BY gdp.game_id, gdp.release_year, gdp.developer;
PostgreSQL示例:
把GROUP_CONCAT换成STRING_AGG即可:
STRING_AGG(DISTINCT gg.genre_name, ', ') AS game_genres
这样查询结果只会返回一行,同时包含所有关联的类型和角色,正好匹配详情页的展示需求!加DISTINCT是为了避免同一类型/角色因表中重复记录而多次出现。
方法3:拆分查询(高并发/大数据量场景更高效)
如果游戏的类型、角色数量特别多,JOIN后的数据量会爆炸式增长,这时候拆分三次查询在应用层组合反而更高效:
- 先查基础数据:
SELECT * FROM game_data_primary WHERE game_id = 123;
- 再查关联类型:
SELECT genre_name FROM game_genre WHERE game_id = 123;
- 最后查关联角色:
SELECT character_name FROM game_cast WHERE game_id = 123;
在后端代码里把这三部分数据拼接起来展示,既避免了重复数据,也减轻了数据库的查询压力。
内容的提问来源于stack exchange,提问作者Prashant Pandey
相关产品推荐
相关产品推荐

