题目如下:
create table candidate(
id int(11),
name varchar(50)
);
create table vote(
id int(11),
candidate_id int(11)
);
编写一个SQL查询来报告获胜候选人的名字(即获得最多选票的候选人)。 生成测试用例以确保 只有一个候选人赢得选举。
输入:
Candidate table:
+----+------+
| id | name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
+----+------+
Vote table:
+----+-------------+
| id | candidate_Id |
+----+-------------+
| 1 | 2 |
| 2 | 4 |
| 3 | 3 |
| 4 | 2 |
| 5 | 5 |
+----+-------------+
输出:
+------+
| name |
+------+
| B |
+------+
解释:
候选人B有2票。候选人C、D、E各有1票。
获胜者是候选人B。
最初的思路如下
1: 分组统计每个候选人的投票数 select candidate_id, count(id) as cnt from vote group by candidate_id ;
2: 计算最大的投票数的候选人ID
- 错误示范
select
max(cnt)
from (
select
candidate_id, count(id) as cnt
from vote
group by candidate_id
) group by candidate_id
- 示范2
select
max(cnt)
from (
select
candidate_id, count(id) as cnt
from vote
group by candidate_id
) group by candidate_id
- 示范3 --
select
c.name
from candidate c
inner join (
select
max(cnt) as mt, candidateId
from (
select
candidateId ,count(id) as cnt
from vote
group by candidateId
) M
)F on c.id = F.candidateId
3: 关联候选人表查询结果
最终正确答案如下:
select
c.name
from candidate c
inner join (
select
candidateId, count(id) as cnt
from Vote
group by candidateId
# 获取分组的最大值
order by count(id) desc
limit 1
) M on c.id = M.candidateId
参考题解2(听说效率会提高)
select name
from candidate where id = (
select
candidateId
from vote
group by candidateId
order by count(*) desc
limit 1
)
参考题解3(窗口函数 + 排序)
select
name
from (
select
a.name
-- 以 group by分组后 在窗口函数以 count(b.id) 进行降序排列
-- 相当于实现了 候选人 的排名
, dense_rank() over(order by count(b.id) desc) as rnk
from candidate a
join vote b
on a.id = b.candidateid
group by b.candidateId
) t where t.rnk = 1;
## 这个SQL相当于 实现了每个候选人的排名, 然后我们获取第一个即可.
select
a.name
, dense_rank() over(order by count(b.id) desc) as rnk
from candidate a
join vote b
on a.id = b.candidateid
group by b.candidateId
在leetcode执行结果如下:
{"headers": ["name", "rnk"], "values": [["B", 1], ["D", 2], ["C", 2], ["E", 2]]}
可以知道排名结果如下:
B 1
D 2
C 2
E 2
问题总结
其实获取分组排序的最大值可以通过 **排序 + limit** 即可轻松获取;
可是我开始的 时候没有想到, 通过再分组获取max.