Access 2016:查询仅返回各playerId首个记录的问题排查
问题分析与解决办法
咱们先拆解下你遇到的问题:你原查询的核心问题出在GROUP BY子句同时包含了playerId和bowlingStyle。
SQL里的GROUP BY是用来把相同字段值的记录归为一组的,你现在把两个字段都放进去,意味着数据库会把「playerId相同且bowlingStyle也相同」的记录当成一组。这样一来,同一个playerId如果有不同的bowlingStyle,就会被分成多个独立的组,自然就会返回多条该playerId的记录,完全不符合你“每个playerId只返回第一条记录的bowlingStyle”的需求。
接下来给你几种不同数据库环境下的正确写法,你可以根据自己用的数据库来选:
如果你用的是Access(因为你原查询用了First函数)
Access里的First函数如果直接GROUP BY playerId,其实可以拿到每组的第一条记录,但要注意必须先确保记录的顺序是你想要的(比如按插入时间或主键排序),否则First的结果可能不符合预期。推荐用子查询先定位每个playerId的第一条记录:
-- 假设你的表有主键ID,用MIN(ID)获取每个playerId最早的记录ID SELECT l.playerId, l.bowlingStyle FROM Lineups l INNER JOIN ( SELECT playerId, MIN(ID) AS FirstRecordId FROM Lineups GROUP BY playerId ) sub ON l.ID = sub.FirstRecordId;
如果没有主键,也可以先排序再分组:
SELECT First(playerId) AS playerId, First(bowlingStyle) AS bowlingStyle FROM ( SELECT playerId, bowlingStyle FROM Lineups ORDER BY playerId, [记录创建时间字段] -- 这里替换成能确定顺序的字段 ) AS SortedLineups GROUP BY playerId;
如果你用的是MySQL/SQL Server
这类数据库支持窗口函数,用ROW_NUMBER()可以很清晰地实现需求:
SELECT playerId, bowlingStyle FROM ( SELECT playerId, bowlingStyle, -- 按playerId分组,按排序字段(比如主键、创建时间)给每条记录编号 ROW_NUMBER() OVER (PARTITION BY playerId ORDER BY [排序字段]) AS rn FROM Lineups ) t WHERE rn = 1; -- 只取每组的第一条记录
如果你用的是PostgreSQL
PostgreSQL有个更简洁的写法,用DISTINCT ON:
SELECT DISTINCT ON (playerId) playerId, bowlingStyle FROM Lineups ORDER BY playerId, [排序字段]; -- 排序字段决定哪条是该playerId的第一条记录
核心思路就是:只按playerId分组(或者按playerId分区),然后明确指定“第一条记录”的判定规则(比如按主键从小到大、按插入时间先后),这样就能保证每个playerId只返回一条包含首个bowlingStyle的记录了。
内容的提问来源于stack exchange,提问作者rob
相关产品推荐
相关产品推荐

