SQL 문제풀이 복습
문제 링크
recursive cte도 쓰고
이동평균도 구해야 하는 hard 문제.
1트(8/31) 때와는 다르게 이번에는 recursive cte를 제외하면
다른 cte는 만들지 않고 서브쿼리로만 한번에 해결했다.
대신 window 함수의 생긴 모양이 조금 복잡해졌는데,
그리고 where 조건을 써서 month를 10월 이내로 제한하면
12월까지의 이동평균을 구할 수 있는데,
저걸 쿼리에 바로 적용하면 11월, 12월 데이터가 아예 빠져버리면서
10월에 구한 이동평균의 값이 틀어지게 되므로,
연산 결과를 한 번 a라는 인라인뷰로 감싼 다음에
where 조건을 써 주어야 한다.
(이동평균을 구하는 등의 문제에서 매번 나오는 패턴)
WITH recursive cte
AS
(
SELECT 1 AS "month"
UNION ALL
SELECT month+1
FROM cte
WHERE month < 12)
SELECT month,
average_ride_distance,
average_ride_duration
FROM (
SELECT cte.month,
round(avg(sum(ifnull(ride_distance,0))) over(ORDER BY month rows BETWEEN current row AND 2 following),2) AS "average_ride_distance",
round(avg(sum(ifnull(ride_duration,0))) over(ORDER BY month rows BETWEEN current row AND 2 following),2) AS "average_ride_duration"
FROM cte
LEFT JOIN Rides r
ON cte.month = month(r.requested_at)
AND year(requested_at) = '2020'
LEFT JOIN AcceptedRides a
ON r.ride_id = a.ride_id
GROUP BY 1) a
WHERE month <= 10
ORDER BY 1;
문제 링크
1트(4/22), 2트(6/16) 때의 풀이와 비교하면
확실히 쿼리가 깔끔해진 것 같다는 생각이 든다.
굳이 cte를 만들거나 어렵게 join할 필요 없이
case when과 집계함수를 쓰면 간단할 문제.
SELECT machine_id,
round(avg(CASE
WHEN activity_type = 'end' THEN timestamp
end) - avg(CASE
WHEN activity_type = 'start' THEN timestamp
end), 3) AS "processing_time"
FROM Activity
GROUP BY 1;
문제 링크
문자열을 다루는 문제.
upper와 lower, 그리고 substr과 concat을 쓸 수 있으면 간단하다.
아래는 중간 풀이 결과.
select
user_id,
upper(left(name,1)),
lower(substr(name,2)),
concat(upper(left(name,1)),lower(substr(name,2))) as "name"
from Users;

아래는 정답 쿼리.
SELECT user_id,
concat(upper(LEFT(name, 1)), lower(substr(name, 2))) AS "name"
FROM Users
ORDER BY 1;
오늘 프로그래머스 문제는 너무 간단해서
따로 리뷰라고 할 만한 건 없었음.
문제 링크
SELECT count(*) AS "FISH_COUNT"
FROM FISH_INFO f
JOIN FISH_NAME_INFO fi
ON f.FISH_TYPE = fi.FISH_TYPE
WHERE FISH_NAME IN ( 'BASS', 'SNAPPER' );
SELECT id,
length
FROM FISH_INFO
ORDER BY 2 DESC,
1 ASC
LIMIT 10;
SELECT count(*) AS "FISH_COUNT"
FROM FISH_INFO
WHERE year(TIME) = '2021';
SELECT concat(max(LENGTH), 'cm') AS "MAX_LENGTH"
FROM FISH_INFO;
문제 링크
join과 서브쿼리 활용 문제.
SELECT id,
fn.FISH_NAME,
f.LENGTH
FROM FISH_INFO f
JOIN (SELECT fish_type,
max(length) AS "length"
FROM FISH_INFO
GROUP BY 1) a
ON f.FISH_TYPE = a.FISH_TYPE
AND f.LENGTH = a.LENGTH
LEFT JOIN FISH_NAME_INFO fn
ON fn.FISH_TYPE = a.FISH_TYPE
ORDER BY 1;