Database/MSSQL Server

[MSSQL] NULL 비교

데이터엔지니어 주형권 2023. 12. 12. 09:00
반응형

MSSQL

 

 

안녕하세요. 

이 글은 제가 예전에 작성하였던 네이버 블로그의 글을 다시 올린 글입니다. 다소 기존의 글보다 내용의 퀄리티가 떨어질 수 있으니 이점 유의해주시기 바랍니다. 이 글을 작성하였을 당시의 연차가 2년 차여서 글 쓰는 실력도 없었고 배우면서 정리던 단계라서 많이 부족합니다.

 

들어가며...

NULL은 RDB에서 개념을 정확하게 알고 있어야 합니다. NULL은 공백이 아닙니다. 그래서 NULL을 포함하냐? 하지 않냐? 는 굉장히 중요합니다. 데이터엔지니어, 데이터분석가 두 직업을 하면서도 분명히 알고 있어야 합니다. 그래서 꼭 RDB의 NULL이 아니더라도 BigQuery , Redshift 등의 모든 데이터를 SQL을 사용하는 곳에서 NULL은 알고 있어야 합니다. 

 

또한 NULL의 경우 취급 방식이 밴더사(Oracle , Mysql 같은..) 마다 다를 수 있기 때문에 꼭 각 밴더사의 NULL을 알고 계시면 좋습니다.

NULL을 한방에 설명한 사진

 

이 글은 MSSQL 2012에서 테스트 하였습니다. 버전이 올라가면서 다르게 결과가 나올 수 있으니 이 점 꼭 유의해주세요.


1) 테스트해보기

만약에 테이블에서 어떠한 값을 찾고자 한다고 가정해 보겠습니다. "AdventureWorks2008" DB에 Production.product라는 테이블에 Color의 열은 Null을 가질 수 있습니다.. 한번 조회해 보도록 하겠습니다. (여기서 AdventureWorks2008 DB는 MSSQL에서 기본적으로 제공하는 테스트 DB입니다.)

 

USE AdventureWorks2008
GO

SELECT * FROM Production.Product

 

Production.product 테이블의 SELECT 결과는 다음과 같습니다.

Production.product

 

Color 칼럼에 NULL값 들이 많이 있는 것을 볼 수 있습니다.

여기서 만약에 우리가 Color가 red인 열을 찾는다고 가정해 보겠습니다.

SELECT * FROM Production.Product
WHERE Color = 'red'

 

Color red를 찾았을 때의 결괏값은 다음과 같습니다.

Color red의 SELECT 결과값

 

정확히 Production.product 테이블에서 Color가 Red인 값을 찾아왔습니다. 하지만 Red가 아닌 값을 찾는다면 어떨까요?

SELECT * FROM Production.Product
WHERE Color <> 'red'

 

Color red가 아닌 결과값은 다음과 같습니다.

Color red가 아닌 SELECT 결과값

 

 

분명히 Red가 아닌 열들을 가져왔습니다.. 하지만 NULL인 열은 전혀 가져오지 못했습니다. 비교할 때 NULL은 분명히 Red는 아니지만 어떠한 값도 아니기 때문에 값을 비교 자체를 할 수 없기 때문입니다.

 

여기서 만약에 요구조건에서 NULL을 미포함한 Red가 아닌 값을 요구한다면 분명히 이 결과는 맞습니다. 하지만 NULL을 포함한다고 한다면? 그 이 결과는 분명히 잘못된 값입니다. 그렇기 때문에 다음과 같이 쿼리를 날릴 수 있습니다. (NULL은 아직 미입력으로 볼 수도 있기 때문에 Red가 아닌 것에 포함해야 할 수 있습니다.)

 

-- 1번
SELECT ProductID,Color
FROM Production.Product
WHERE Color <> 'Red' OR Color IS NULL

-- 2번
SELECT ProductID,Color
FROM Production.Product
WHERE ISNULL(Color,'') <> 'Red'

-- 3번
SELECT ProductID,Color
FROM Production.Product
WHERE COALESCE(Color,'') <> 'Red'

 

위의 3가지 방법 모두 NULL이거나 Red가 아닌 열들을 보여줍니다. (칼럼들은 보기 쉽게 하기 위해 2개만 출력) 1번은 직접 NULL과 비교하는 IS NULL을 사용하였고 2번, 3번은 NULL을 빈값(공백)으로 바꾸어 주면서 비교하도록 하였습니다. 또한 이와 마찬가지로 NULL은 크다(<)와 작다(>)를 인식을 못합니다.


2) 다른 방식으로 테스트해보기

다음 예를 통해 간단히 보면 다음과 같습니다.

CREATE TABLE DBO.TEST_5
(
 NAME   VARCHAR(20)
,AGE    INT
)
GO

 

위의 쿼리를 이용하여 테이블을 만들고 값을 삽입해서 테스트해보겠습니다.

INSERT INTO DBO.TEST_5  VALUES ('Joo',20)
INSERT INTO DBO.TEST_5  VALUES ('Hyoung',5)
INSERT INTO DBO.TEST_5  VALUES ('Kwon',NULL)

 

아래의 쿼리를 통해서 SELECT 해봅니다.

SELECT * FROM DBO.TEST_5
WHERE AGE >= 5 AND AGE < 30

 

SELECT의 결괏값은 아래와 같습니다.

SELECT 결과

 

위의 2개의 열만 검색이 됩니다. Kwon은 나이를 아직 입력하지 않은 것이지 5~30살 사이에 해당되지 않은 것이 아니기 때문입니다. 그러므로 데이터가 잘못될 수 있는 것입니다.(물론 포함 안 한다고 명시할 경우는 맞지만...)

 

또한 추가적으로 이러한 경우도 있습니다.

 

WHERE 절에서 NOT IN과 함께 사용하는 하위 쿼리에서 NULL 결과를 반환하는 경우입니다.

만약에 하위 쿼리에서 NULL이 포함되어 있다면 외부 쿼리에서는 아무런 결과가 출력되지 않습니다.

 

Production.Product 테이블의 Color열에서 사용할 수 있는 색깔이 저장된 테이블이 있다고 가정해 보자 이 테이블의 데이터 중에 Production.Product 테이블의 데이터에서 사용하고 있지 않은 색을 찾아내는 쿼리를 만들어 보겠습니다.

 

CREATE TABLE Production.ColorList
(
 Color NVARCHAR(15) NOT NULL
PRIMARY KEY
)
GO

INSERT INTO Production.ColorList(Color)

SELECT Color
FROM Production.Product
WHERE Color IS NOT NULL
GROUP BY Color

 

다음과 같이 Production.ColorList 테이블을 만들고 색 열들을 만들어서 넣어보도록 하겠습니다.

SELECT 결과

 

9가지의 컬러가 Production.ColorList 테이블에 등록되었습니다.

여기에 추가적으로 다음 4가지 색을 넣어 보도록 하겠습니다.

INSERT INTO Production.ColorList(Color)
VALUES ('Purple'),('Orange'),('Lemon'),('Gold')

 

이제 13가지 색이 생겼습니다. 이제 우리는 Production.Product 테이블에서 사용되지 않는 색을 찾아내고자 합니다. 그렇다면 필자가 마지막에 추가한 4가지 색 이외에 색이 나와야 합니다.

 

다음과 같이 쿼리를 날려보도록 하겠습니다.

SELECT Color
FROM Production.ColorList
WHERE Color NOT IN(SELECT Color FROM Production.Product)

 

쿼리에는 문제가 없지만 결과는 아무것도 나오지 않습니다. 왜일까요?

바로 NULL이 출력되기 때문입니다. 여기서 하위쿼리에는 NULL이 포함되기 때문에 비교 자체를 할 수 없는 것입니다. 

 

이 쿼리는 다음과 같이 입력해야지 정확한 쿼리입니다.

이렇게 입력한다면 우리가 원하는 결과를 얻을 수 있습니다.

SELECT Color
FROM Production.ColorList
WHERE Color NOT IN
(SELECT Color FROM Production.Product
 WHERE Color IS NOT NULL)

 


출처 

https://blog.naver.com/dba_burning/60209825180

 

MsSQL Server _ Null 비교

  NULL 그놈에 NULL...   NULL은 항상 필자를 헷갈리게 한다. 특히 null을 비교할때...

blog.naver.com

 

반응형