Algorithm / / 2025. 3. 27. 17:21

[LeetCode SQL] 1321: Restaurant Growth 코드 리뷰 및 분석

LeetCode SQL 1321. Restaurant Growth 코드 리뷰 및 분석 (요약)

 

쿼리

# Write your MySQL query statement below

with DailyTotals as (
    select visited_on, sum(amount) as amount
    from customer
    group by visited_on
)

select dt1.visited_on, sum(dt2.amount) as amount, round(avg(dt2.amount),2) as average_amount 
from DailyTotals dt1
join DailyTotals dt2 on dt2.visited_on 
between date_sub(dt1.visited_on, interval 6 day) and dt1.visited_on
group by dt1.visited_on having dt1.visited_on >= date_add(min(dt2.visited_on), interval 6 day)

 

 

쿼리 분석

  • 구조: WITH 절을 사용하여 일별 매출 합계를 계산하는 공통 테이블 표현식(CTE) DailyTotals를 정의하고, 이 CTE를 셀프 조인하여 7일간의 이동 합계 및 평균을 계산합니다.
  • DailyTotals CTE:
    • customer 테이블에서 visited_on으로 그룹화하여 날짜별 총 매출(amount)을 미리 계산합니다.
  • 메인 SELECT:
    • DailyTotals CTE를 dt1(기준일)과 dt2(7일 기간 내 날짜)로 셀프 조인합니다.
    • JOIN 조건 (dt2.visited_on BETWEEN DATE_SUB(dt1.visited_on, INTERVAL 6 DAY) AND dt1.visited_on)을 사용하여 각 dt1 기준일에 대해 해당 날짜를 포함한 과거 7일간의 모든 dt2 레코드를 연결합니다.
    • GROUP BY dt1.visited_on을 사용하여 기준일별로 결과를 그룹화합니다.
    • SUM(dt2.amount)AVG(dt2.amount)를 계산하여 7일간의 총 매출 합계와 평균 매출을 구하고, ROUND 함수로 평균값을 소수점 둘째 자리까지 반올림합니다.
    • HAVING dt1.visited_on >= DATE_ADD(MIN(dt2.visited_on), INTERVAL 6 DAY) 조건을 사용하여, 그룹 내에서 최소 7일치의 데이터가 확보된 날짜(dt1.visited_on)부터 결과를 필터링합니다. 이는 7일 이동 평균/합계를 계산할 수 있는 첫 날부터 결과를 보여주기 위함입니다.
  • 결과: 각 해당 visited_on 날짜와 그 날까지의 7일간 amount(총 매출), average_amount(평균 매출)를 반환합니다.

 

코드 리뷰

  • 정확성: 쿼리는 문제의 요구사항(특정 날짜까지의 7일간 이동 합계 및 평균 계산, 최소 7일 데이터 확보 조건, 반올림)을 논리적으로 정확하게 구현했습니다. HAVING 절의 조건도 기능적으로는 올바르게 동작하여 시작일을 필터링합니다.
  • 가독성: WITH 절(CTE)을 사용하여 쿼리를 단계별로 나누었기 때문에, 일별 집계 로직과 7일 계산 로직이 분리되어 가독성이 좋습니다. 테이블과 컬럼 별칭(dt1, dt2 등)도 명확합니다. 다만, HAVING 절의 조건 로직은 직관적으로 이해하는 데 약간의 시간이 필요할 수 있습니다.
  • 효율성: CTE를 통해 일별 집계를 미리 수행하는 것은 효율적입니다. 하지만, 날짜 범위(BETWEEN)를 사용한 셀프 조인은 DailyTotals의 행 수에 따라 성능이 크게 저하될 수 있습니다 (N7번 비교 발생 가능). 데이터 양이 많은 경우, *윈도우 함수 (Window Functions: SUM() OVER (...), AVG() OVER (...))** 를 사용하는 것이 일반적으로 훨씬 효율적이며, 이동 집계를 위한 표준적인 SQL 접근 방식입니다.
  • 스타일: CTE 사용, 표준 SQL 함수(SUM, AVG, ROUND, DATE_SUB, DATE_ADD, MIN) 활용 등 일반적인 SQL 작성 스타일에 부합합니다.

 

한 줄 요약 (Nutshell)

제공된 쿼리는 CTE와 셀프 조인을 활용하여 LeetCode 1321번 문제의 7일 이동 매출 집계 요구사항을 정확히 해결하지만, 대용량 데이터에서는 윈도우 함수를 사용하는 것이 성능상 더 효율적인 대안입니다.

 

# Write your MySQL query statement below

with DailyTotals as (
    select visited_on, sum(amount) as amount
    from customer
    group by visited_on
),
RollingCalculations AS (
    -- 2. 윈도우 함수를 사용하여 7일 이동 합계, 평균, 및 윈도우 내 데이터 수 계산
    SELECT visited_on,
        -- 현재 행 포함 이전 6개 행(총 7일)의 합계
        SUM(amount) OVER (ORDER BY visited_on ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS amount,
        -- 현재 행 포함 이전 6개 행(총 7일)의 평균
        AVG(amount) OVER (ORDER BY visited_on ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS average_amount_unrounded,
        -- 현재 행 포함 이전 6개 행(총 7일)의 데이터 개수 (7일치 데이터가 있는지 확인용)
        COUNT(amount) OVER (ORDER BY visited_on ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS window_days_count
    FROM DailyTotals
)
-- 3. 최종 결과 선택 및 필터링
SELECT visited_on, amount,
    -- 평균값을 소수점 둘째 자리까지 반올림
    ROUND(average_amount_unrounded, 2) AS average_amount
FROM RollingCalculations
-- 윈도우에 정확히 7일치의 데이터가 있는 경우만 결과에 포함
WHERE window_days_count = 7
ORDER BY visited_on; -- 결과를 날짜순으로 정렬
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유