SQL中如何比较同一列两值的COUNT并筛选未完赛选手
问题描述
现有数据表 RunnerActions(简化后结构如下):
| Runner | Action |
|---|---|
| John | Start |
| Amy | Start |
| Susan | Start |
| John | Finish |
| Amy | Start |
| Amy | Finish |
需求:获取选手列表,包含已开始赛事数量(StartCount)和已完成赛事数量(FinishCount),且仅显示未完成所有已开始赛事的选手。
期望输出:
| Runner | StartCount | FinishCount |
|---|---|---|
| Amy | 2 | 1 |
| Susan | 1 | 0 |
当前疑问:需要统计同一列中两个不同值的数量,但COUNT通常配合WHERE子句,这里需要两个不同的WHERE条件,不确定能否在单条SQL中实现?现有尝试的SQL语句:
SELECT Runner, COUNT(Action), * FROM RunnerActions WHERE Action = 'Start'
解决方案
完全可以在单条SQL中实现,核心是使用条件聚合(通过CASE WHEN配合聚合函数),不需要拆分多个查询或WHERE子句。
实现代码
SELECT Runner, COUNT(CASE WHEN Action = 'Start' THEN 1 END) AS StartCount, COUNT(CASE WHEN Action = 'Finish' THEN 1 END) AS FinishCount FROM RunnerActions GROUP BY Runner HAVING COUNT(CASE WHEN Action = 'Start' THEN 1 END) > COUNT(CASE WHEN Action = 'Finish' THEN 1 END);
逻辑说明
- 条件计数:
CASE WHEN会对符合条件的行返回1,不符合的返回NULL;而COUNT函数会自动忽略NULL值,从而实现对指定Action的精准计数。 - 分组统计:
GROUP BY Runner按选手维度聚合数据,确保每个选手只返回一行统计结果。 - 过滤结果:
HAVING子句用来筛选未完成所有赛事的选手——只有当StartCount大于FinishCount时,才保留该选手的记录(排除像John这种已完成所有赛事的选手)。
替代写法(用SUM实现)
也可以用SUM替代COUNT,逻辑完全一致:
SELECT Runner, SUM(CASE WHEN Action = 'Start' THEN 1 ELSE 0 END) AS StartCount, SUM(CASE WHEN Action = 'Finish' THEN 1 ELSE 0 END) AS FinishCount FROM RunnerActions GROUP BY Runner HAVING StartCount > FinishCount;
内容的提问来源于stack exchange,提问作者leigero
相关产品推荐
相关产品推荐

