SQL查询问题:为何无法返回参与游戏数量最少的所有经销商?
分析你的SQL查询问题及修正方案
咱们先拆解你当前查询的核心问题,再一步步给出正确的解法:
原查询的问题
- WHERE EXISTS子句完全无效:你写的子查询只是按游戏类型分组计数,和
Dealer表的行没有任何关联逻辑。这个条件只会判断Game表是否存在分组数据,只要有数据,所有经销商都会被保留,完全没统计每个经销商的实际参与游戏数量。 - TOP 1无法处理多个最小值的情况:就算统计逻辑正确,
TOP 1只能返回第一条匹配的经销商,当多个经销商的参与游戏数同为最小值时,其他符合条件的结果会被直接忽略。
正确的查询方案
下面提供两种可行的写法,都能返回所有参与游戏数量最少的经销商:
方案1:使用窗口函数(推荐,SQL Server 2008+支持)
这种写法更简洁,一步到位统计并筛选:
WITH DealerGameStats AS ( SELECT d.number, CONCAT(d.firstName, ' ', d.surName) AS 'full name', COUNT(g.DealerInGame) AS total_games, MIN(COUNT(g.DealerInGame)) OVER () AS min_total_games FROM Dealer d LEFT JOIN Game g ON d.number = g.DealerInGame GROUP BY d.number, d.firstName, d.surName ) SELECT number, [full name] FROM DealerGameStats WHERE total_games = min_total_games
- 用
LEFT JOIN是为了包含从未参与任何游戏的经销商(他们的total_games会是0),如果只需要统计参与过至少一次游戏的经销商,把LEFT JOIN改成INNER JOIN即可。 MIN(...) OVER ()会计算所有经销商中的最小游戏数,不需要额外子查询。
方案2:先获取最小值再筛选
如果你习惯分步逻辑,可以先计算最小游戏数,再匹配对应的经销商:
-- 第一步:计算所有经销商的最小参与游戏数 DECLARE @MinGameCount INT; SELECT @MinGameCount = MIN(game_count) FROM ( SELECT COUNT(*) AS game_count FROM Game GROUP BY DealerInGame ) AS DealerGameCounts; -- 第二步:筛选出参与数等于最小值的经销商 SELECT d.number, CONCAT(d.firstName, ' ', d.surName) AS 'full name' FROM Dealer d LEFT JOIN ( SELECT DealerInGame, COUNT(*) AS game_count FROM Game GROUP BY DealerInGame ) g ON d.number = g.DealerInGame WHERE ISNULL(g.game_count, 0) = @MinGameCount;
内容的提问来源于stack exchange,提问作者Felix Kim
相关产品推荐
相关产品推荐

