SQL 코드카타
문제 링크
어려워서 한동안 묵혀놨었던 문제.
머리가 차분할 때 풀어보니 생각보다 어렵지 않게 풀렸다.
아래는 완성된 정답 쿼리.
WITH recursive cte
AS
(
SELECT 1 AS "month"
UNION ALL
SELECT month+1
FROM cte
WHERE month < 12),
a
AS
(
SELECT c.month,
ifnull(sum(ride_distance),0) AS "total_distance",
ifnull(sum(ride_duration),0) AS "total_duration"
FROM cte c
LEFT JOIN rides r
ON c.month = month(r.requested_at)
AND date_format(r.requested_at,'%Y-%m') BETWEEN '2020-01' AND '2020-12'
LEFT JOIN acceptedrides a
ON r.ride_id = a.ride_id
GROUP BY 1),
b
AS
(
SELECT month,
total_distance,
total_duration,
avg(total_distance) over(ORDER BY month rows BETWEEN 2 preceding AND current row) AS "avg_distance_temp",
avg(total_duration) over(ORDER BY month rows BETWEEN 2 preceding AND current row) AS "avg_duration_temp"
FROM a),
result
AS
(
SELECT month,
ifnull(round(lead(avg_distance_temp,2) over(ORDER BY month),2),0) AS "average_ride_distance",
ifnull(round(lead(avg_duration_temp,2) over(ORDER BY month),2),0) AS "average_ride_duration"
FROM b)
SELECT month,
average_ride_distance,
average_ride_duration
FROM result
WHERE month <= 10
ORDER BY 1;
위의 3번~4번 단계를 하나로 압축하려면
이동평균을 구하는 단계에서 쿼리를 다르게 짜면 된다.
처음 풀 때는 몰라서 preceding 2와 current row 사이의 이동평균을 구하고
lead를 써서 2칸을 당겨오는 불필요한 연산을 추가했지만,
current row와 2 following으로 쿼리를 바꾸면
굳이 result CTE를 만들 필요가 없게 된다.
아래는 조금 더 축약된 버전의 정답 쿼리.
WITH recursive cte
AS
(
SELECT 1 AS "month"
UNION ALL
SELECT month+1
FROM cte
WHERE month < 12),
a
AS
(
SELECT c.month,
ifnull(sum(ride_distance),0) AS "total_distance",
ifnull(sum(ride_duration),0) AS "total_duration"
FROM cte c
LEFT JOIN rides r
ON c.month = month(r.requested_at)
AND date_format(r.requested_at,'%Y-%m') BETWEEN '2020-01' AND '2020-12'
LEFT JOIN acceptedrides a
ON r.ride_id = a.ride_id
GROUP BY 1),
b
AS
(
SELECT month,
round(avg(total_distance) over(ORDER BY month rows BETWEEN current row AND 2 following),2) AS "average_ride_distance",
round(avg(total_duration) over(ORDER BY month rows BETWEEN current row AND 2 following),2) AS "average_ride_duration"
FROM a)
SELECT month,
average_ride_distance,
average_ride_duration
FROM b
WHERE month <= 10
ORDER BY 1;
오늘의 문제풀이는 여기까지.
내일은 묵혀놨던 문제 중 또 하나를 해결해 봐야겠다.
프로그래밍을 해야 하는 게 아니라면 Leetcode 문제는 완벽하게 다 풀어서 끝을 내야지.