일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- mysql설치 #mysql #mysqluser #mysqlworkbench
- model_selection
- 그로스해킹
- sklearn
- 서말리포켓
- 리텐션
- fundbox
- 바로팜
- 활성화
- 역설구조
- 머신러닝
- retention
- 인게이지먼트
- CAC
- 선정산서비스
- 데이터분석
- 전환율
- BM분석
- aarrr
- 올라
- 비즈니스모델
- pmf
- 핀테크
- 퍼널분석
- 셀프스토리지
- activation
- 한장으로끝내는비즈니스모델100
- allra
- 코호트
- 팔방이익구조
- Today
- Total
데이터로그😎
[SQL기본] NOT IN 사용 시 주의사항 본문
Hacker Rank에서 Binary Tree Nodes 문제에 대한 SQL 쿼리식을 작성하던 와중, 중요한 사실을 알아버렸다..!
NOT IN 사용 시 주의해야 할 사항인데, 쿼리를 업무에서 쓰는 사람이라면 꼭 알아 둘 것..! ☠️
0. 데이터 소개
Column | Type | 컬럼 설명 |
N | Integer | Binary Tree의 노드 값 |
P | Integer | N의 Parent |
1. 문제
https://www.hackerrank.com/challenges/binary-search-tree-1/problem?isFullScreen=false
Write a query to find the node type of Binary Tree ordered by the value of the node.
- Root: If node is root node.
- Leaf: If node is leaf node.
- Inner: If node is neither root nor leaf node.
1.1. Sampel Output
1 Leaf
2 Inner
3 Leaf
5 Root
6 Leaf
8 Inner
9 Leaf
2. 풀이
노드타입을 구하는 조건을 다음과 같이 생각해보았다.
- Root : P colum이 Null일것
- Leaf: N이 P column에 들어있지 않을 것 (즉, Parent list에 없는 N을 구한다는 의미 = Parent가 아닌 N = 하위 항목이 없는 N = Leaf)
- Inner: Root도, Leaf도 아닌 N
이러한 조건들을 반영해 처음 작성했던 쿼리문은 다음과 같다. 그러나 나름 정확한 답을 제출했다고 생각했음에도 계속 Error가 뜨는 것이 아닌가... 그래서 chat gpt의 도움을 얻던 와중 중요한 사실을 알아버렸다!
SELECT N, CASE WHEN P is NULL THEN 'Root'
WHEN N NOT IN (select distinct p from bst) THEN 'Leaf'
ELSE 'Inner' end as nodeType
FROM BST
ORDER BY N asc;
[배운점 1] NOT IN 을 사용할 때는 subquery 에 NULL값이 하나라도 들어가면, 비교 전체가 망가진다!
위의 내가 작성했던 쿼리문을 예시로 들어보겠다. CASE WHEN 절에서 Leaf 값을 구할 때 NOT IN 절을 사용했다. 그런데 만약 ( select distinct p from bst) 안에 Null이 하나라도 있으면 NOT IN 조건의 결과가 UNKNOWN이 되어버린다. 따라서 비교 실패!
N=1
P 목록 = (2,5,Null)
***SQL의 판단 회로를 알아보자.
1 ≠ 2 ? ➡️ Yes
1 ≠ 5 ? ➡️ Yes
1 ≠ Null ? ➡️ Unknown
결론적으로 "1이 (2,5,Null) 안에 없다고 확신할 수 없다"라는 결론을 짓게 된다.
따라서 결과는 FALSE가 아니라 "UNKNOWN"이 되어버려서 where 절에서 필터링 할 수 없다.
***해결법1: WHERE P IS NOT NULL 조건을 추가한다.
SELECT DISINCT P FROM BST WHERE P IS NOT NULL--> 이렇게 하면 NULL이 제거되어 NOT IN 이 정상 작동한다.
SELECT N, CASE WHEN P is null then 'Root'
WHEN N NOT IN (select distinct p from bst where p is not null) THEN 'Leaf' ELSE 'Inner' end as nodeType
FROM BST
order by n asc;
***해결법2: NOT IN 대신 NOT EXISTS 비교문을 사용한다.
NULL값에 민감한 NOT IN 대신 NULL값에 영향을받지 않는 EXISTS를 사용할 수도 있다. (where p is not null 구문을 추가하지 않아도 되어서 오히려 더 간단!
by n asc;
SELECT N, CASE WHEN P is null then 'Root'
WHEN NOT EXISTS (select 1 from bst as child where bst.n=child.p) THEN 'Leaf' ELSE 'Inner' end as nodeType
FROM BST
order by n asc;
[배운점 2] IN 을 사용할 때는 subquery 에 NULL값이 있어도 괜찮다.
IN (...) 은 비교 중에 하나라도 참이면 OK다. 즉, 비교 대상에 NULL이 있어도, 다른 값이 매칭만 된다면 OK다.
단, 비교 대상이 NULL IN (...) 이면 비교 자체가 UNKNOWN이 되어버려 필터링이 되지 않는다.
SELECT *
FROM 테이블
WHERE 1 IN (2, 3, NULL); -- → FALSE (1은 없음)
SELECT *
FROM 테이블
WHERE 3 IN (2, 3, NULL); -- → TRUE (3 있음)
SELECT *
FROM 테이블
WHERE NULL IN (2, 3, NULL); -- → UNKNOWN (비교 불가)
비교 방식 | NULL이 있어도 괜찮은가? | 결과에 영향이 있는가? |
IN (...) | ✅ 괜찮음 | 일부 경우 영향 X |
NOT IN (...) | ❌ 안 괜찮음 | 전체비교 실패 |
3. 결론
- IN (...): NULL 있어도 대체로 OK
- NOT IN (...): NULL 있으면 무조건 문제됨
→ 꼭 WHERE ~ IS NOT NULL 넣어줘야 함!
'# 1. 언어 > # 1.1. SQL' 카테고리의 다른 글
[SQL기본] DISTINCT, 제대로 알고 쓰자! (0) | 2025.04.10 |
---|---|
[mysql] Workbench user생성하기 (0) | 2025.03.12 |
[MySQL] 데이터 모델링 (0) | 2024.01.10 |
[MySQL] JOIN 🆚 서브쿼리 (0) | 2024.01.04 |
[MySQL] 데이터베이스 & 유저 생성 (0) | 2024.01.01 |