1070. Product Sales Analysis III : leetcode

오유찬·2026년 1월 3일

SQL

목록 보기
32/71
--  상품이 팔린 첫 해에 관한 레코드 출력

--  1. 첫 해에 팔린 상품의 sale_id
WITH first_year AS (SELECT      sale_id, year
                    FROM        Sales
                    GROUP BY    product_id
                    HAVING      year = MIN(year))

-- Recursive? GROUP BY + HAVING(MIN(year))
SELECT      product_id, year as first_year, quantity, price
FROM        Sales
WHERE       sale_id IN (SELECT sale_id FROM first_year)
sale_idproduct_idyearquantityprice
11002008105000
21002009125000
72002011159000

이 test case에서는 통과하는데
다른 test case에서는 아예 output이 출력되지 않았다. CTE에서 year에 관련된 그룹 조건절이 잘못된 건 알겠는데 왜 결과가 출력조자 되지 않았을까?

그룹화를 하고 그 안에서 가장 오래된 행(MIN(year))만 필터링해서 출력한다는 의도를 가지고 CTE를 작성했지만 SQL에서 그렇게 작동되지 않는다. GROUP BY를 했을 때, 압축을 진행한 후에 HAVING 절로 진입한다.
이때,COUNT 함수는 임의의 행을 세는 함수이기 때문에 특정 행을 선정할 필요가 없어 잘 작동하지만 내가 작성한 비교문은 특정 행을 선택해야 하기 때문에 엄격한 SQL에서는 에러가 뜨고 느슨한 SQL에서는 임의로 첫 행을 선택해서 비교한 후 필터링하는 등 생각과는 다르게 작동한다.

A안

WITH first_year AS (SELECT      product_id, MIN(year) as 1st_year
                    FROM        Sales
                    GROUP BY    product_id)

SELECT      product_id, year as first_year, quantity, price
FROM        Sales
WHERE       (product_id, year) IN (SELECT product_id, 1st_year FROM first_year)

상품코드와 연도의 조합으로 조건절을 작성하여 진행한다.
다른 방식으로는 Window function이 있다.

B안

WITH year_rnk AS (SELECT  product_id, year, quantity, price,
                RANK() OVER(PARTITION BY product_id ORDER BY year ASC) as rnk
                FROM    Sales)

select      product_id, year as first_year, quantity, price
from        year_rnk
where       rnk = 1

둘 다 정답을 제출해보면 B안이 A안보다 많이 느린 것을 알 수 있는데, 이는 CTE에서 B안이 모든 행에서 연도에 관하여 정렬을 하기 때문임을 어렵지 않게 예상할 수 있다.
이때, 데이터가 INDEX로 정렬이 되어있는 상태라면 두 쿼리의 차이는 거의 나지 않을텐데

profile
열심히 하면 재밌다

0개의 댓글