SQL 문제풀이 복습
문제 링크
2트(9/4)에서는 이 문제를 풀 때 offset이라는 명령어를 썼다.
'offset을 쓰게 되면 출력된 결과에서 한 행을 건너뛰게 되므로
2번째로 높은 salary를 구할 수 있게 되'는 원리인데,
사실 이렇게 풀어도 똑같이 답이 나온다.
(중요한 건 해당하는 값이 없을 때는 null이 반환된다는 점)
SELECT Max(salary) AS "SecondHighestSalary"
FROM Employee
WHERE salary < (SELECT Max(salary)
FROM Employee);
문제 자체가 어려운 건 아닌데
해당하는 값이 없을 때 null을 띄우도록 하는 게 어려운 점.
CTE를 써도 안 되고, window함수를 쓰면 가능은 한데 쿼리가 너무 복잡해진다.
offset을 쓰거나 (단, CTE로 쓰면 안되고 인라인뷰로)
아니면 오늘의 풀이처럼 서브쿼리를 활용하면 될 듯.
문제 링크
recursive cte를 만들 수 있으면 그 뒤로는 간단한 문제.
subtasks_count가 가장 큰 subtask_id이기도 하므로
1이 나올 때까지 값을 하나씩 줄여가면서
union한 결과를 full_task에 저장하고,
그 뒤로는 Executed와 join해서
아직 완료되지 않은 건을 찾아주기만 하면 됨.
WITH recursive full_task
AS
(
SELECT task_id,
subtasks_count AS "all_task"
FROM Tasks
UNION ALL
SELECT task_id,
all_task - 1
FROM full_task
WHERE all_task > 1)
SELECT f.task_id,
f.all_task AS "subtask_id"
FROM full_task f
LEFT JOIN Executed e
ON f.task_id = e.task_id
AND f.all_task = e.subtask_id
WHERE e.subtask_id IS NULL
ORDER BY 1,
2;
문제 링크
피벗테이블 만드는 문제.
그렇게 안 어렵다.
select
product_id,
max(case when store = 'store1' then price end) as "store1",
max(case when store = 'store2' then price end) as "store2",
max(case when store = 'store3' then price end) as "store3"
from Products
group by 1;
문제 링크
서브쿼리와 join, concat을 조합한 문제.
모든 user_id가 다 필요한 건 아니므로
서브쿼리를 써서 3개 이상 게시글을 올린 유저부터 추린 후에
그 결과물과 join하고 주소와 전화번호를 불러왔다.
1트 때는 정답 쿼리는 따로 넣어놓지 않았구나..ㅎㅎ
SELECT u.user_id,
nickname,
Concat(city, ' ', street_address1, ' ', street_address2) AS
"전체주소",
Concat(LEFT(tlno, 3), '-', Mid(tlno, 4, 4), '-', RIGHT(tlno, 4)) AS
"전화번호"
FROM used_goods_user u
JOIN (SELECT writer_id
FROM used_goods_board
GROUP BY 1
HAVING Count(*) >= 3) a
ON u.user_id = a.writer_id
ORDER BY 1 DESC;
문제 링크
서브쿼리로 결과를 먼저 만들어 놓고 join을 하든,
join을 한 뒤에 group by having을 쓰든 결과는 같다.
(1트(4/5) 때는 join 먼저 하고 group by로 결과를 나중에 뽑았다)
다만 이번에 풀 때는 join의 가짓수가 너무 많아질 것 같아서
서브쿼리로 결과를 한 번 줄여놓고 join하는 방법을 택함.
SELECT u.user_id,
u.nickname,
a.total AS "TOTAL_SALES"
FROM USED_GOODS_USER u
JOIN (SELECT writer_id,
Sum(price) AS "total"
FROM USED_GOODS_BOARD
WHERE status = 'DONE'
GROUP BY 1
HAVING total >= 700000) a
ON u.user_id = a.writer_id
ORDER BY 3;
문제 링크
where절로 조건을 줄 때 문자를 제어해서 조건을 짜는 문제.
네비게이션 앞이나 뒤에 다른 문자가 올 수 있으므로
앞뒤를 % 기호로 감싸줘야 한다.
SELECT CAR_ID,
CAR_TYPE,
DAILY_FEE,
OPTIONS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%네비게이션%'
ORDER BY 1 DESC;
문제 링크
group by와 having
그리고 대여기간을 구하기 위한 datediff만 알면 됨
SELECT CAR_ID,
Round(Avg(Datediff(END_DATE, START_DATE) + 1), 1) AS "AVERAGE_DURATION"
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY 1
HAVING AVERAGE_DURATION >= 7
ORDER BY 2 DESC,
1 DESC;
문제 링크
똑같이 medium으로 분류되더라도
leetcode 쪽이 훨씬 난이도가 높다.
이 문제는 level3이긴 하지만 정말 간단한 join 문제.
SELECT DISTINCT c.CAR_ID
FROM CAR_RENTAL_COMPANY_CAR c
JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY h
ON c.CAR_ID = h.CAR_ID
WHERE CAR_TYPE = '세단'
AND Month(START_DATE) = '10'
ORDER BY 1 DESC;