개요
DB에서 SELECT을 수행할 때 WHERE에 다양한 조건을 걸어야 할 때가 있습니다. 이 때 WHERE절에 "커피의 양이 50ml, 100ml, 150ml"와 같이 "같은 칼럼이지만 다른 값이 들어와야 하는 경우"도 있고 "커피, 우유, 콜라, 사이다"와 같이 "아예 상황에 따라 다른 칼럼을 사용해야 하는 경우"도 있습니다. 제 문제는 두번째 케이스였지만 먼저 첫번째 경우도 알아보겠습니다.
조건에 따라 결과 출력하기
첫번째의 경우는 CASE WHEN THEN으로 해결이 가능합니다. 그런데 해당 기능을 쓰면 결과적으로 "단순히 값"만 표현할 수 있습니다. ORACLE 공식문서 예시에서 SELECT절에 CASE WHEN THEN을 사용하는 예제가 있습니다. 아래 SELECT하는 칼럼을 먼저 살펴보고, 이후 WHERE에서 사용법을 살펴보겠습니다.
- CASE 칼럼명 WHEN 값 THEN 결과
CASE 칼럼명
WHEN '값1' THEN '결과1'
WHEN '값2' THEN '결과2'
ELSE '결과3'
END
- CASE WHEN 조건식 THEN 결과
CASE
WHEN '조건식1' THEN '결과1'
WHEN '조건식2' THEN '결과2'
ELSE '결과3'
END
해당 문법과 예시를 보면 "단순한 값"만 표현합니다. 즉, if문처럼 하나의 "절" 단위로 표현을 하고 싶어도 "값"만 구분할 수 있습니다. 따라서 WHERE 에서 CASE WHEN THEN을 쓰려면 다음과 같이 약간의 변형이 필요합니다. 값만 구분할 수 있다는 것은 다시 말하면 "하나의 칼럼"만 표현할 수 있다는 뜻입니다.
- WHERE절에서 조건 분기하기(1) - 정적
SELECT *
FROM tableA
WHERE
NAME = --조건을 걸 칼럼명
CASE
WHEN '조건식1' THEN '결과1'
WHEN '조건식2' THEN '결과2'
ELSE '결과3'
END
조건에 따라서 이름(NAME) 칼럼이 바뀌는 경우는 위처럼 해결이 가능합니다. 하지만 제 쿼리는 조건절에 다양한 칼럼의 케이스를 고려해야 했습니다. 예를 들어, A테이블에서 이름(NAME)으로 구분을 했는데 결과가 없다면, B테이블에서 닉네임(NICKNAME)으로 검색해야 합니다. 이런 경우는 케이스에 따라서 칼럼이 달라지는 경우입니다.
이런 경우 아래에서 처럼 WHERE에서 AND와 OR를 적절하게 활용해야 합니다.
- WHERE절에서 조건 분기하기(2) - 동적
...
WHERE
...
AND ((A.NAME = 'PARK') OR (B.NICKNAME = 'PARK' AND A.NAME IS NULL))
...
AND 이후에 큰 괄호 ( ... ) 안에 OR로 연결해 주면 됩니다. 위의 경우 A테이블의 이름(NAME)이 'PARK'인 경우, 그렇지 않다면 B테이블의 닉네임(NICKNAME)이 'PARK'인 경우를 동시에 검색할 수 있습니다. 이것이 WHERE절에서 다양한 칼럼의 형태를 검색하고 싶은 IF문의 형식입니다. A.NAME IS NULL은 제 저장소에 NAME이 없는 경우가 있기에 명시적으로 알려주기위해 넣은 것입니다. 하나의 조건이 더 들어간다면 다음과 같이 할 수 있습니다.
...
WHERE
...
AND ((A.NAME = 'PARK') OR (B.NICKNAME = 'PARK' AND A.NAME IS NULL) OR (C.NAME = 'PARK'))
...
현재 조건 3개를 검색하도록 했습니다. 즉, A테이블에서 이름이 PARK인 경우 혹은 B테이블에서 닉네임이 PARK인 경우 혹은 C테이블에서 이름이 PARK인 경우 3개의 조건을 확인할 수 있습니다. 혹시 이것 이외에 다양한 조건을 걸고 싶다면 추가적으로 걸면 됩니다.
핵심은 WHERE문에서 IF문을 사용하려면 AND 뒤에 ( ... ) 괄호 안에 모든 것을 OR로 묶어서 넣은 것입니다.
또한 이 모든 조건들을 하나의 큰 괄호 안에 넣어야 합니다.
*잘못된 쿼리문
...
WHERE
...
AND (A.NAME = 'PARK') OR (B.NICKNAME = 'PARK' AND A.NAME IS NULL) OR (C.NAME = 'PARK')
...
*대괄호를 빼면 AND와 OR 조건이 꼬여버립니다.
*참고
'학습 > DB' 카테고리의 다른 글
Spring Data Repository Interface (0) | 2021.08.29 |
---|---|
SQL select 쿼리 문법 순서 (0) | 2021.08.28 |
CDATA란? (0) | 2021.08.27 |
oracle ROWNUM & ROW_NUMBER (0) | 2021.08.27 |
JOIN vs WHERE 차이점 (0) | 2021.05.12 |