postgresql nullif 함수는 특정 조건을 만족할 때 널 값을 돌려주기 위해 사용합니다. 아래와 같이 쓸 수 있습니다.
nullif(expr1, expr2)
expr1과 expr2가 같으면 null을, 다르면 expr1을 돌려줍니다.
1번 쿼리를 봅시다. nullif(0, 0)를 출력하라고 합니다. 0과 0은 같습니다.
따라서 nil이 결과로 나옵니다.
이제, 2번 쿼리를 보겠습니다. expr1은 0이고, expr2는 2네요. 0과 2는 다른가요? 따라서, expr1인 0이 출력될 겁니다. 결과를 볼까요?
결과를 보니까 0이 나오네요. nullif(expr1, expr2)의 동작 방식을 순서도로 표현하면 아래와 같습니다.
expr1과 expr2가 같으면 nil을 출력한다. 그렇지 않으면 expr1을 출력합니다. 고로 간단한 조건을 만족하는 경우 nil 을 출력해야 한다. 이런 경우에 case when 대신에 사용하면 좋겠습니다. 조금이라도 조건이 복잡해지면 case when 으로 바꾸는 것이 좋습니다. 아래 예제들을 보면 확실히 이해가 가실 듯 합니다.
1번째 문제. expr2와 일치하지 않으면 nil을, 그렇지 않으면 expr1을 출력하게 합시다. 한 마디로 반전 조건입니다. 먼저, nullif(expr1, expr2)은 expr1이 expr2와 같으면 nil을, 다르면 expr1을 돌려줍니다.
이제 expr1이 nil이면 expr1이, expr1과 같다면 nil이 출력되게 하면 되는데요. 그럴려면, 1번째 인자에 expr1을, 2번째 인자에 nullif(expr1, expr2)를 넣어주면 되겠지요?
expr1이 expr2와 다를 때에는 굵은색 화살표를 따라갑니다. 같을 경우 얇은 화살표를 따라가는 구조입니다. 맞는지 볼까요?
expr1에 3, expr2에 3을 넣었습니다. nullif(3, 3)에 의해 3과 3이 같으므로 nil이 나옵니다. 3과 nil은 다르기 때문에, 3이 나옵니다.
expr1에 6, expr2에 3을 넣었습니다. 6과 3은 다르니, 안쪽 nif 함수에서는 6이 나옵니다. 그런데, 6과 6은 같기 때문에, 여기서 nil이 나오게 되는 것입니다. 상당히 복잡합니다.
expr1이 3이거나 6인 경우에 nil이 나오게 합시다. 그렇지 않으면 expr1이 나오게 해 봅시다.
먼저 expr1이 3이라면 nil이 나오게 하고, 아니라면 expr1이 나오게 합시다. 이것은 nullif(expr1, 3)으로 하면 됩니다. 이 결과를 가지고 또 nullif 함수를 써 주면 되는데요. null은 6과 다르기 때문에 null이 나옵니다.
고로 아래와 같이 써 주면 됩니다.
select nullif(nullif(expr1, 3), 6)
expr1이 3이거나 6이면 nil을, 그렇지 않으면 expr1을 돌려준다.
정확한 결과가 나오는지 쿼리로 확인해 봅시다. 3, 6, 7을 넣어서 테스트 해 보겠습니다.
3과 6은 3 또는 6이므로 null이 떨어지지만, 7은 그렇지 않아요. 따라서 7이 리턴됩니다.
nullif(nullif(expr1, expr2), expr3)
expr1이 expr2 또는 expr3이면 nil을, 아니면 expr1을 돌려줍니다.
2개의 조건 절만 걸렸는데도 복잡하지요? 더 많아지면 얼마나 복잡해 질까요? 따라서, 이러한 경우에는 case when 절을 쓰는 것을 고려하는 것이 좋습니다. 사용법도 복잡하지 않으니, 공식 문서를 참고하시면 좋겠습니다.