240907_TIL

J Lee·2024년 9월 7일

아무리 사소하더라도 배움이 없는 날은 없다.

SQL 문제풀이 복습

문제 링크
6/30에 이어 두 번째로 풀게 된 문제.

첫 번째 풀이 때는 CTE도 2개를 만들고
조건을 꽤나 복잡하게 썼었는데,
오늘은 생각보다 훨씬 더 간단하게 풀렸다.

그냥 조인의 조건 + 문제에서 요구하는 조건만 잘 넣으면
CTE를 쓸 것도 없이 한방에 해결할 수 있었음.
Cancellation Rate를 구할 때 분자 자리에 들어가는
Count + Case when 조합만 신경쓸 것. (end 처리)

SELECT t.request_at                                AS "Day",
       Round(Count(CASE
                     WHEN t.status LIKE 'cancelled%' THEN t.id
                   end) / Count(DISTINCT t.id), 2) AS "Cancellation Rate"
FROM   trips t
       LEFT JOIN users u
              ON t.client_id = u.users_id
       LEFT JOIN users u2
              ON t.driver_id = u2.users_id
WHERE  u.banned <> 'YES'
       AND u2.banned <> 'YES'
       AND request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP  BY 1;

문제 링크

SELECT player_id,
       Min(event_date) AS "first_login"
FROM   activity
GROUP  BY 1; 

문제 링크
7/4에 이어 두 번째로 풀게 된 문제.

처음 풀이 때는 CTE를 만들어서
플레이어별로 가장 빠른 날짜를 구해 놓고
본 쿼리에서 join을 해서 id와 빠른 날짜를 매칭시키는 방식으로 풀었다.

WITH first
     AS (SELECT player_id,
                Min(event_date) AS first
         FROM   activity
         GROUP  BY 1)
SELECT first.player_id,
       a.device_id
FROM   first
       INNER JOIN activity a
               ON first.player_id = a.player_id
                  AND first.first = a.event_date; 

오늘은 CTE 없이 서브쿼리로 해결했고,
window 함수 중 rank를 써서 플레이어별로 ranking이 1인,
즉 가장 빠른 event_date에 해당하는 player_id와 device_id만 갖고오도록 했다.

SELECT player_id,
       device_id
FROM   (SELECT player_id,
               device_id,
               Rank()
                 OVER(
                   partition BY player_id
                   ORDER BY event_date) AS "ranking"
        FROM   activity) a
WHERE  ranking = '1';

풀이가 겹치는 걸 피하고 싶어서
일부러 첫 번째 풀이와는 다르게 접근해 봤다.
여러 개념을 두루 리마인드하기 위해서라도 이 방법이 좋을 듯.

profile
기본기를 소홀히 하지 말자

0개의 댓글