[프로그래머스 lv4] 오프라인/온라인 판매 데이터 통합하기

데프·2024년 5월 23일

SQL문제풀이

목록 보기
7/7
post-thumbnail

👉 문제 바로가기(프로그래머스)

# 문제

Q. 온라인 판매 테이블과 오프라인 판매테이블이 있을 때 이 둘을 통합하라.

온라인 판매 테이블과 오프라인 판매 테이블의 차이점은 user_id의 유무뿐인 문제

# 정답

SELECT
	#3
    TRIM(SALES_DATE) SALES_DATE
    , PRODUCT_ID
    , IF(USER_ID = -1, NULL, USER_ID) USER_ID #2
    , SUM(SALES_AMOUNT) SALES_AMOUNT
FROM
    (
    SELECT *
    FROM ONLINE_SALE ONL
    WHERE YEAR(SALES_DATE) = 2022 AND MONTH(SALES_DATE) = 3
    UNION ALL #1
    SELECT OFFLINE_SALE_ID, -1, PRODUCT_ID, SALES_AMOUNT, SALES_DATE
    FROM OFFLINE_SALE OFL
    WHERE YEAR(SALES_DATE) = 2022 AND MONTH(SALES_DATE) = 3
    ) A
GROUP BY
    ONLINE_SALE_ID, PRODUCT_ID, USER_ID
ORDER BY
    1
    , 2
    , 3
;
  1. UNION ALL로 합치고
  2. NULL값 처리해주고
  3. 날짜 출력형식 맞추기

만 해주면 되는 간단한 문제이다.
다만 테스트케이스에는 없지만 하루에 여러 판매데이터가 있을 경우 GROUP BY를 하지 않을 경우 오답이 된다.
문제에선 GROUP BY를 하지 않아도 정답이지만 문제의 취지에 맞춰 생각하면 GROUP BY를 해주는게 맞다고 생각한다.

# 성능고찰

그리고 성능면에서 두가지를 얘기해보자면
1. UNION보단 UNION ALL의 부하가 더 적다. UNION은 중복 검사를 하기 때문. 이 문제에선 온오프라인 판매 데이터가 중복될 일은 없으니 UNION ALL을 사용하는 것이 바람직하다.
(여담으로 UNION ALL이 가능한 테이블이라면 한 테이블로 존재하는 것이 효율적이다.)

2. '2022년 3월'을 찾는 WHERE절을 위 아래 쿼리에 총 두번 썼는데, 이와 같이 서브쿼리 안에서 행 수를 줄여서 나가는 것이 일반적으로 좋다.
정확히는 WHERE과 같은 필터링 작업 시 인덱스를 사용해야 하는데 UNION ALL과 같은 연산은 임시테이블을 생성한다. 이런 임시 테이블에는 인덱스가 적용되지 않기 때문에 인덱스를 사용할 수 있는 변형 전 테이블에서 필터링 작업을 해야한다.

(참고 : https://sewonzzang.tistory.com/45 )

profile
정보의 홍수를 기록하는 데프의 로그

0개의 댓글