SQL
카타
문제 114. 626. Exchange Seats if(ifnull), case when 조건문 활용
Write a solution to swap the seat id of every two consecutive students. If the number of students is odd, the id of the last student is not swapped.
Return the result table ordered by id in ascending order.
The result format is in the following example.
Example 1:
Input:
Seat table:
+----+---------+
| id | student |
+----+---------+
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
+----+---------+
Output:
+----+---------+
| id | student |
+----+---------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+----+---------+
Explanation:
Note that if the number of students is odd, there is no need to change the last one's seat.
풀이 과정
select id,
case when id%2 = 0 then lag(student) over (order by id)
when id%2 = 1 then lead(student) over (order by id)
end as student
from seat
| id | student |
| -- | ------- |
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | null |
일다는 보이는 대로 직관적으로 윈도우 함수를 써서 테스트를 해봤는데 마지막 홀수만 null값이 나왔고,
null을 간단하게 처리할 수 있지 않을까하는 생각에 case when 조건문을 ifnull로 묶어봤다.
최종 정답
select id,
ifnull(case when id%2 = 0 then lag(student) over (order by id)
when id%2 = 1 then lead(student) over (order by id)
end, student) as student
from seat
그랬더니 정말 정답이 나왔음ㅋㅋ
문제 해결 포인트 : case when도 if로 묶어 낼 수 있다
문제115. 1341. Movie Rating
Write a solution to:
- Find the name of the user who has rated the greatest number of movies. In case of a tie, return the lexicographically smaller user name.
- Find the movie name with the highest average rating in February 2020. In case of a tie, return the lexicographically smaller movie name.
The result format is in the following example.
풀이과정
*풀기 전 생각 정리
1. 최다 레이팅 한 사람과 최고 평점 영화를 같은 곳에다 출력해야하니 일단 둘을 따로 구한 다음 union 등으로 합쳐주면 되겠다고 생각
2. 그러니 관건은 둘을 먼저 따로 구하는 쿼리를 작성해 보는 것.
3. 이러나 저러나 참 이상한 문제임
덧. lexicographically smaller라고 하길래 당연히 글자수가 적어서 smaller라고 생각했는데, 사전상 앞에 있는 것을 그렇게 표현하는 거였음;;;
1. 최다 레이팅 사람 구하기
서브쿼리 통한 시도 : 실패 - 서브쿼리에 limit 사용 불가
select name
from users
where user_id in (select user_id,
count(*),
char_length(user_id)
from movierating
group by user_id
order by 2 desc, 3 asc
limit 1);
이렇게 풀면 금방 끝나겠다 생각했는데, MySQL의 현재 버전은 서브쿼리 내에 limit를 사용하는 것을 지원하지 않는다는 에러 뜸;;;
이런 식으로 해서 먼저 원하는 user_id가 나오는지 테스트해봤고
select user_id
from movierating
group by user_id
order by count(*) desc, user_id asc
limit 1
join을 사용해서 아래와 같이 했더니 원하는 대로 Daniel이 출력됨. 이제 2번만 구하고서 합쳐주면 됨!
select u.name as results
from movierating m join users u using(user_id)
group by m.user_id
order by count(*) desc, u.name asc
limit 1
2. 최고 평점 구하기 은 이렇게 간단하게 작성했고
select m.title as result
from movierating mr join movies m using(movie_id)
where created_at <= '2020-02-28'
group by movie_id
order by avg(mr.rating) desc, m.title asc
limit 1
3. 합치기 : 최종정답 - union all로 간단하게 완성
(select u.name as results
from movierating m join users u using(user_id)
group by m.user_id
order by count(*) desc, u.name asc
limit 1)
union all
(select m.title as result
from movierating mr join movies m using(movie_id)
where created_at like '2020-02%'
group by movie_id
order by avg(mr.rating) desc, m.title asc
limit 1)
*test cases 중 각각의 쿼리로 추출된 사람명이랑 영화명 둘 다 Rebecca로 같은 예제가 있어서 union으로 했을 시에는 오답이 났고, 다시 union all로 바꿔줘야했다. 실전에서 주의해야할 사항인듯
포인트 : 두 테이블을 union 할 때 별다른 언급이 없으면 union all을 사용할 것
TMI
-개인과제 optional인 4번 문제도 어떻게 풀려 했으나...
오늘 점심 먹고서 반나절 내내 붙들어 매고서도 결국 제대로 풀어내진 못한 듯.
공부 좀 더 하고 풀어볼 걸 그랬나? 암튼 간만에 주말 일정이 여유로우니 내일 풀어봐야겠다 꼭