일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @GeneratedValue
- @GenericGenerator
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- async/await
- AVG
- AWS
- Azure
- bind
- builder
- button
- c++
- c++ builder
- c03
- Callback
- case when
- CCW
- chat GPT
- CICD
- Collections
- Combination
- combinations
- Comparator
- Today
- Total
기록
[SQL] NULL이 포함된 연산은 NULL로 평가된다. 본문
연산과 조건절에서의 NULL
업무에서 데이터 조회를 위한 쿼리를 작성하다가, NULL을 잘못 처리하는 실수를 했다. 이번기회에 다시 NULL을 어떻게 처리해야 하는지 공부하고, 고민해보려고한다. 실제 업무의 데이터는 꽤 복잡하고 민감한 정보라, 아래의 예제는 일반적인 상황으로 치환한 사례이다.
아래에서는 "사용자 계정" 정보를 담고 있는 user_accounts
테이블과 "월별 사용량" 정보를 담고 있는 monthly_usage
테이블을 조인하여 특정 사용자의 월별 사용 정보를 검색하는 과정에서 발생한 문제와 해결 방안을 소개한다.
테이블 예시
user_accounts
테이블
account_id | user_name | usage_month |
---|---|---|
0000001 | 홍길동 | 2024-05 |
0000002 | 이순신 | 2024-05 |
0000003 | 강감찬 | 2024-05 |
monthly_usage
테이블
usage_month | account_id | usage_status |
---|---|---|
2024-05 | 0000001 | 1 |
2024-05 | 0000002 | 3 |
문제 발생 및 원인 분석
LEFT JOIN
을 사용하여 두 테이블을 조인할 때, mu.usage_status NOT IN ('3')
조건으로 인해 usage_status
가 NULL인 강감찬의 정보가 결과에서 제외되는 문제가 발생하였다.
SQL에서는 NULL 값을 '값이 없음'으로 처리하며, NULL과의 비교는 TRUE나 FALSE가 아닌 NULL을 결과로 반환한다. 따라서, mu.usage_status
가 NULL인 경우, 해당 조건은 TRUE나 FALSE로 평가되지 않아 결과 집합에서 해당 행이 제외된다.
해결 방안
- 명시적 NULL 처리
명시적으로 NULL 값을 처리하여 문제를 해결할 수 있다. 아래 쿼리는 mu.usage_status
가 NULL인 경우도 결과에 포함한다.
SELECT * FROM user_accounts ua
LEFT OUTER JOIN monthly_usage mu
ON ua.account_id = mu.account_id
WHERE (mu.usage_status NOT IN ('3') OR mu.usage_status IS NULL)
AND ua.usage_month = '2024-05'
NVL
함수 활용
NVL
함수를 사용하여 NULL 값을 특정 값으로 대체하는 방법도 있다. 이 경우, NULL인 mu.usage_status
를 '0'으로 간주하여 조건을 만족시키므로, 모든 사용자 정보가 결과에 포함되게 된다.
SELECT * FROM user_accounts ua
LEFT OUTER JOIN monthly_usage mu
ON ua.account_id = mu.account_id
WHERE NVL(mu.usage_status, '0') NOT IN ('3')
AND ua.usage_month = '2024-05'
주의사항
NVL
함수를 사용할 때는 해당 컬럼에 대한 인덱스 활용이 어려워질 수 있으므로, 성능 저하의 가능성을 고려해야 한다. 가능한 한 다른 방법을 우선적으로 고려하는 것이 좋다.
결론
NULL을 포함하는 어떤 연산도 그 결과는 NULL로 평가된다
SQL에서 NULL을 포함하는 어떤 연산(예: +, -, *, /)도 그 결과는 NULL로 평가된다. 예를 들어, NULL + 10의 결과는 NULL이다. 이는 SQL이 NULL을 '알 수 없는 값'으로 처리하며, 알 수 없는 값에 어떤 연산을 적용하더라도 결과 역시 '알 수 없음'이라고 판단하기 때문이다.NULL을 처리하는 방법
- IS NULL / IS NOT NULL: column_name IS NULL은 컬럼 값이 NULL일 때 true를 반환.
- NVL, COALESCE 함수: 이 함수들은 NULL 값을 다른 값으로 치환할 때 사용된다.
'제대로 이해하기' 카테고리의 다른 글
Java/Labeled Loop (0) | 2024.04.26 |
---|---|
[이해하기] DB/ANSI SQL, JOIN (0) | 2022.09.11 |
[이해하기] java/initialize block (0) | 2022.09.10 |
[이해하기] Android/API와 SDK (0) | 2022.05.24 |
[이해하기] kotlin/컬렉션 (0) | 2022.03.27 |