SQL查询中GROUP BY时无需逐一枚举即可选取所有列的方法
解决方法:无需枚举所有列即可选取Users全列
当然可以!当Users表包含大量列时,逐一枚举确实很繁琐,这里有几种实用的方案帮你避开在SELECT和GROUP BY里列全40列的麻烦:
方案1:先筛选符合条件的用户ID,再关联主表
这种方法是先通过UserSkills表聚合出满足技能条件的用户ID,再关联Users表直接获取所有列,完全不用处理GROUP BY多列的问题:
WITH QualifiedUsers AS ( SELECT us.UserId FROM @UserSkills AS us WHERE us.SkillId IN (149, 305) GROUP BY us.UserId HAVING COUNT(*) = 2 ) SELECT u.* FROM @Users AS u INNER JOIN QualifiedUsers qu ON u.Id = qu.UserId;
原理:先对UserSkills做轻量聚合,只保留符合条件的用户ID,再关联主表查询全列,既简洁又高效。
方案2:使用窗口函数标记符合条件的用户
通过窗口函数按用户ID分组统计技能数量,筛选出符合要求的记录后再关联主表取全列:
SELECT DISTINCT u.* FROM @Users AS u INNER JOIN ( SELECT us.UserId, COUNT(*) OVER(PARTITION BY us.UserId) AS SkillCount FROM @UserSkills AS us WHERE us.SkillId IN (149, 305) ) AS us ON u.Id = us.UserId WHERE us.SkillCount = 2;
原理:窗口函数COUNT(*) OVER(PARTITION BY us.UserId)会为每个用户的技能记录标记该用户符合条件的技能总数,筛选出总数为2的记录后,通过DISTINCT去重得到唯一用户,再关联主表获取全列。
方案3:用EXISTS检查多技能(适合技能数量少的场景)
如果你的技能条件是固定的少量技能(比如这里的2个),可以用多个EXISTS子查询直接验证用户是否同时拥有这些技能:
SELECT u.* FROM @Users AS u WHERE EXISTS ( SELECT 1 FROM @UserSkills us1 WHERE us1.UserId = u.Id AND us1.SkillId = 149 ) AND EXISTS ( SELECT 1 FROM @UserSkills us2 WHERE us2.UserId = u.Id AND us2.SkillId = 305 );
原理:这种方法不需要聚合操作,直接检查用户是否存在对应技能的记录,可读性强,对于少量技能的场景效率也很高。
注意事项
- 使用
SELECT u.*会自动包含Users表的所有列,后续表结构变化(新增/删除列)时,查询结果会同步更新,这可能正是你需要的;但如果有性能优化需求,明确指定所需列会更稳妥,不过针对40列的场景,上述方案已经足够便捷。
内容的提问来源于stack exchange,提问作者Miguel Moura
相关产品推荐
相关产品推荐

