197. Rising Temperature
처음쿼리 2000ms
select W1.id
from Weather W1
join Weather W2
on DATEDIFF(W1.recordDate, W2.recordDate) = 1
where W1.temperature > W2.temperature;
인덱스 타도록 개선 800ms
select W1.id
from Weather W1
join Weather W2
on W1.recordDate = W2.recordDate + INTERVAL 1 DAY
where W1.temperature > W2.temperature;
다른 사람들의 쿼리들도 봤는데, 날짜 제한같은 편법들을 이용한거 외에는 고성능 쿼리는 없는 것 같다. 셀프조인이나 셀프조인과 다름없는 쿼리들과 비슷한 맥락
1661. Average Time of Process per Machine
select a1.machine_id, ROUND(AVG(a2.timestamp - a1.timestamp),3) as processing_time
from Activity a1
join Activity a2
on a1.process_id = a2.process_id
and a1.machine_id = a2.machine_id
and a1.timestamp < a2.timestamp
group by a1.machine_id;
서브쿼리로도 풀 수 있긴 한데, 이게 차라리 깔끔한 것 같다. 근데 왜 easy지..
577. Employee Bonus
select name, bonus
from Employee
left join Bonus
on Employee.empId = Bonus.empId
where bonus < 1000 or bonus is null;
바로 다음 문제인데, 왜 이것들이 같이 묶여있는지 모르겠다. 이런건 스킵해야겠다.
1280. Students and Examinations
select
s.student_id,
s.student_name,
sub.subject_name,
coalesce(count(e.student_id), 0) as attended_exams
from
students s
join
subjects sub on 1=1
left join
examinations e on s.student_id = e.student_id and sub.subject_name = e.subject_name
group by
s.student_id,
s.student_name,
sub.subject_name
order by
s.student_id,
sub.subject_name;
- students 테이블과 subjects 테이블을 on 1=1로 단순하게 조인하여 모든 학생과 모든 과목의 조합을 생성
- 생성된 학생-과목 쌍을 examinations 테이블과 left join으로 연결
- coalesce(count(e.student_id), 0)을 사용하여 참석 기록이 없는 경우 0으로 반환
1번을 cross join을 이용해서 가능하다고 하는데, cross join을 쓰는게 생각이 안났다.
select
m.name
from
employee e
join
employee m on e.managerId = m.id
group by
m.id, m.name
having
count(e.id) >= 5;
이건 왜 medium일까
1934. Confirmation Rate
select
s.user_id,
round(ifnull(avg(case when c.action = 'confirmed' then 1 else 0 end), 0), 2) as confirmation_rate
from
signups s
left join
confirmations c on s.user_id = c.user_id
group by
s.user_id;
- 그냥 집계함수 쓰는 문제
- 먼저 모든 결과를 포함하기 위해 left join + ifnull함수 사용
- user_id groupby 이후 action칼럼 + 조건식으로 avg