문제/프로그래머스

[프로그래머스 / MySQL] 업그레이드 할 수 없는 아이템 구하기

icodesiuuuu 2025. 2. 21. 18:13

문제

https://school.programmers.co.kr/learn/courses/30/lessons/273712

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

❌ 처음 작성한 쿼리

SELECT item_id, item_name, rarity 
FROM item_info 
WHERE item_id NOT IN ( 
    SELECT DISTINCT parent_item_id 
    FROM item_tree 
)
order by item_id desc
;
  • 이 쿼리에서 parent_item_id를 SELECT했는데, NULL 값이 포함될 수 있음
  • parent_item_id는 ROOT 아이템에 대해 NULL 값을 가지니까, 결국 NULL이 포함된 결과가 NOT IN 서브쿼리 안에 들어가게 됨

 

NULL 값이 포함되면 NOT IN이 문제가 되는 이유

NOT IN을 사용할 때, 비교 대상 리스트에 NULL 값이 하나라도 포함되면, SQL의 삼항 논리(boolean logic) 에 의해 비교 결과가 UNKNOWN이 돼서 항상 FALSE로 처리됨

 
WHERE item_id NOT IN (NULL, 0, 1, 2)

 

이러면 item_id = 3 같은 값을 비교할 때

3 NOT IN (NULL, 0, 1, 2) → UNKNOWN (즉, FALSE 취급)

그래서 모든 비교가 FALSE가 되어 원하는 결과를 얻지 못하는 문제가 발생!

 

IS NOT NULL을 추가하자!

방법 1: WHERE parent_item_id IS NOT NULL 추가

 
SELECT item_id, item_name, rarity 
FROM item_info 
WHERE item_id NOT IN (
    SELECT DISTINCT parent_item_id 
    FROM item_tree
    WHERE parent_item_id IS NOT NULL
)
order by item_id desc
;

 

방법 2: NOT EXISTS 사용

SELECT i.item_id, i.item_name, i.rarity 
FROM item_info i 
WHERE NOT EXISTS (
    SELECT 1 
    FROM item_tree t 
    WHERE t.parent_item_id = i.item_id
)
order by item_id desc
;
  • NOT EXISTS는 값을 직접 비교하는 게 아니라, 서브쿼리의 결과 존재 여부만 판단하기 때문에 NULL 문제를 피할 수 있음
  • 즉, item_info에 있는 item_id가 parent_item_id로 존재하지 않는 경우만 선택됨

 

결론

  • NOT IN을 사용할 때 서브쿼리 결과에 NULL이 포함되면 의도한 결과가 나오지 않을 수 있음
  • 해결책
    1. WHERE parent_item_id IS NOT NULL을 추가해서 NULL을 제거
    2. NOT EXISTS를 사용하면 더 안전하게 해결 가능