1194. 锦标赛优胜者
题目中有一个翻译错误,当得分相同时应该是id小的获胜。
本题的关键是得到一个有player_id,group_id,score 组成的初始化表格。
# 自己的方法:得到初始化表格,想想哪不对?
select player_id,group_id, ifnull(m1.first_score,0)+ifnull(m2.second_score,0) score
from players p left join matches m1
on p.player_id=m1.first_player
left join matches m2
on p.player_id=m2.second_player
# 方法1 不对,还没找到哪儿错(确定是获得初始表格代码还是不对)
select group_id,player_id
from
(select group_id,player_id, CASE WHEN @id=group_id THEN @cnt:=@cnt+1
WHEN @id:=group_id THEN @cnt:=1 end cnt
from
(select player_id,max(group_id) group_id, sum(ifnull(m1.first_score,0)+ifnull(m2.second_score,0)) score
from players p left join matches m1
on p.player_id=m1.first_player
left join matches m2
on p.player_id=m2.second_player
GROUP by player_id) t1,(select @id:=0, @cnt:=0) t2
order by group_id,score DESC, player_id) t3
WHERE cnt=1
# 正确的获得初始化表格的方法:不要left join两个表格,使用or 选定多个连表条件
select player_id,max(group_id) group_id, SUM(CASE when p.player_id=m.first_player then first_score
when p.player_id=m.second_player then second_score end) score
from players p left join matches m
on p.player_id=m.first_player or p.player_id=m.second_player
GROUP by player_id
order by player_id
# 方法2 待优化
SELECT a.group_id, a.player_id
FROM (
SELECT a.group_id, a.player_id, CASE WHEN @preCol = group_id THEN @rank := @rank + 1
ELSE @rank := 1 END AS rk, @preCol := group_id
FROM (
SELECT player_id, MAX(group_id) AS group_id, SUM(CASE WHEN a.player_id = b.first_player THEN b.first_score
WHEN a.player_id = b.second_player THEN b.second_score
ELSE 0 END) AS allScore
FROM Players a
LEFT JOIN Matches b
ON a.player_id = b.first_player OR a.player_id = b.second_player
GROUP BY a.player_id) a, (SELECT @preCol := NULL, @rank := 0) r
ORDER BY group_id, allScore DESC, player_id
) a
WHERE a.rk = 1
1204. Last Person to Fit in the Elevator 最后一个进入电梯的人
题目重点:turn是进入电梯的顺序。
# 自己的方法 0.9296
select person_name
from
(select person_name, @sum_weight:=@sum_weight+weight sum_weight
from queue q,(select @sum_weight:=0) t
order by turn) t2
where sum_weight<=1000
order by sum_weight desc
limit 1
1205. 每月交易II
# 超棒的逻辑 0.9126
SELECT date_format(a.trans_date, '%Y-%m') AS month, a.country, COUNT(CASE WHEN state = 'approved' THEN 1 ELSE NULL END) AS approved_count,
SUM(CASE WHEN state = 'approved' THEN amount ELSE 0 END) AS approved_amount,
COUNT(CASE WHEN state IS NULL THEN 1 ELSE NULL END) AS chargeback_count,
SUM(CASE WHEN state IS NULL THEN amount ELSE 0 END) AS chargeback_amount
FROM (
SELECT *
FROM Transactions
UNION ALL
SELECT a.trans_id AS id, b.country, NULL, b.amount, a.trans_date
FROM Chargebacks a
JOIN Transactions b ON a.trans_id = b.id) a
WHERE a.state != 'declined' or a.state is null
GROUP BY a.country, date_format(a.trans_date, '%Y-%m')
1212. Team Scores in Football Tournament
这道题可以说是1194题的精华部分的升级版~
注意得分规则
# 自己的方法 应该不错 0.9535
SELECT team_id, MAX(team_name) AS team_name, SUM(CASE WHEN team_id = host_team THEN host_goals
WHEN team_id = guest_team THEN guest_goals
ELSE 0 END) AS num_points
FROM teams a
LEFT JOIN
(SELECT host_team,guest_team, case when host_goals > guest_goals then 3
when host_goals = guest_goals then 1
ELSE 0 end host_goals,
case when host_goals > guest_goals then 0
when host_goals = guest_goals then 1
ELSE 3 end guest_goals
FROM Matches) b
ON a.team_id = b.host_team OR a.team_id = b.guest_team
GROUP BY a.team_id
order by num_points desc,team_id
1225. 报告系统状态的连续日期
# 自己的方法,以后尽量不要利用case在函数中,做赋值操作。还是单独写出来,有时候会报错。 0.6962
select 'failed' period_state, min(fail_date) start_date, max(fail_date) end_date
from
(select fail_date, case when datediff(fail_date,@pre_date) = 1 then @cnt:=@cnt
else @cnt:=@cnt+1 end cnt, @pre_date := fail_date
from failed, (select @pre_date:=null, @cnt:=0) t
where fail_date between '2019-01-01' and '2019-12-31') t1
group by cnt
union all
select 'succeeded' period_state, min(success_date) start_date, max(success_date) end_date
from
(select success_date, case when datediff(success_date,@pre_date) = 1 then @cnt:=@cnt
else @cnt:=@cnt+1 end cnt, @pre_date := success_date
from succeeded, (select @pre_date:=null, @cnt:=0) t
where success_date between '2019-01-01' and '2019-12-31') t2
group by cnt
order by start_date
# 方法2:一开始就合并数据源,而不是合并结果。 0.6456
SELECT flag AS period_state, MIN(ds) AS "start_date", MAX(ds) AS "end_date"
FROM (
SELECT a.ds, CASE WHEN datediff(a.ds, @preCol) = 1 AND @preFlag = flag THEN @groupId
ELSE @groupId := @groupId + 1 END AS groupId, @preCol := a.ds, @preFlag := a.flag, a.flag
FROM (
SELECT fail_date AS ds, 'failed' AS flag
FROM Failed
UNION ALL
SELECT success_date AS ds, 'succeeded' AS flag
FROM Succeeded) a, (SELECT @preCol := NULL, @preFlag := NULL, @groupId := 0) s
WHERE ds between '2019-01-01' AND '2019-12-31') a
GROUP BY groupId
ORDER by start_date
1241. 每个帖子的评论数
这是一道简单题 但是感觉自己写的有点复杂了
# 自己的方法 0.91
select a.sub_id post_id, ifnull(count(parent_id),0) number_of_comments
from
(select distinct sub_id
from submissions
where parent_id is null) a
left join
(select distinct sub_id,parent_id
from submissions
where parent_id is not null) b
on a.sub_id=b.parent_id
group by a.sub_id
order by post_id
# 方法2 0.6651
SELECT
post_id,
COUNT( DISTINCT S2.sub_id ) AS number_of_comments
FROM
( SELECT DISTINCT sub_id AS post_id FROM Submissions WHERE parent_id IS NULL ) S1
LEFT JOIN Submissions S2
ON S1.post_id = S2.parent_id
GROUP BY S1.post_id
# 法1
select p.product_id, round(sum(price*units)/sum(units),2) average_price
from
prices p
join
(select distinct a.* from unitssold a) u
on p.product_id=u.product_id and u.purchase_date between start_date and end_date
group by p.product_id
# 法2 直接 join不去重 也可以通过
select p.product_id, round(sum(price*units)/sum(units),2) average_price
from
prices p
join
unitssold u
on p.product_id=u.product_id and u.purchase_date between start_date and end_date
group by p.product_id
1270. All People Report to the Given Manager
简单说一下本题的要求:找到直接或间接给老板汇报工作的员工。
SELECT employee_id EMPLOYEE_ID
FROM employees
WHERE employee_id not in
(select employee_id from employees
where manager_id in
(select employee_id from employees
where manager_id in
(select employee_id from employees
where manager_id in
(select employee_id
from employees
where employee_id=manager_id and employee_id != 1))))
and employee_id != 1