📢 들어가며
업무 중 콤마를 포함한 스트링으로 DB 데이터를 조회해야하는 일이 생겼다.
간단히 설명하자면, "apple,banana,orange"라는 데이터를 콤마로 구분하여 각 단어를 뽑아내고
fruit 라는 컬럼에서 apple, banana, orange가 존재한다면 select 해오는 일이었다.
자바에서 작업하고 List<String>
로 넘겨 Mybatis에서 IN
작업을 해주려고 했었는데,
PostgreSQL ANY
만으로도 간단히 해결하는 방법을 찾아내어 포스팅해보려고 한다.
💬 ANY 란?
서브 쿼리의 반환 값과 비교할 때 사용하는 연산자.
서브 쿼리의 반환 값 중 하나라도 일치하면 조건이 성립된다.
JavaScript 유저라면 '하나라도 일치하면' 이라는 문구에서 some()
과 비슷한 느낌을 받았을 것이다.
실제로 SQL 에도 SOME
이라는 연산자가 존재하고, 이는 ANY
와 동의어이다.ANY
가 쓰일 수 있는 모든 곳에 SOME
을 쓸 수 있다.
이렇게만 봐선 아직 잘 모르겠다. 아래 예제를 살펴보자.
💬 ANY 예제
SELECT title
FROM film
WHERE length >= ANY(
SELECT MAX( length )
FROM film
INNER JOIN film_category USING(film_id)
GROUP BY category_id );
ANY
내의 서브 쿼리는 카테고리로 그룹 지어진 영화 중 가장 긴 length
(컬럼 명임)를 반환한다는 내용이다.
예를 들어 서브쿼리의 반환 값이 7 이라고 했을 때film
테이블의 length
(컬럼 값)가 7보다 같거나 크면 해당 title
을 반환한다.
즉, ANY는 서브 쿼리의 반환 값과 특정 컬럼을 비교 했을 떄 하나라도 일치한다면 조건이 성립하는 것이다.
위 예제에선 MAX
를 썼기 때문에 서브 쿼리의 반환 값이 하나여서 굳이 ANY를 쓰지 않아도 됐겠지만
반환 값이 여러개인 경우 ANY
가 유용하게 쓰일 수 있다.
위와 같은 서브 쿼리 외에도 function 의 반환 값과도 ANY
를 사용할 수 있다.
"📢 들어가며" 에서 언급한 상황을 시도해보자.
select
fruit
from
food
where
fruit = ANY(string_to_array('apple,banana,orange', ','))
string_to_array
연산자가 보이는가?string_to_array
가 무엇인지도 짚고 넘어가보자.
💡 string_to_array
string_to_array
는 문자열을 특정 문자(구분자)로 나누거나 특정 문자를 null
로 만들고 싶을 떄 사용하는 연산자이다.
string_to_array('문자열', '구분자', '구분자', '구분자'...)
💡 string_to_array 예제
SELECT string_to_array('xx~^~yy~^~zz', '~^~', 'yy');
결과
string_to_array
-----------------
{xx,NULL,zz}
(1 row)
문자열 xx~^~yy~^~zz
에서 ~^~
와 yy
가 null로 대체된 것을 알 수 있다!
다시 ANY
예제로 돌아와보자.
즉, string_to_array('apple,banana,orange', ',')
는{apple,NULL,banana,NULL,orange}
를 반환할 것이다.
이 반환 값이 ANY
를 돌게 되는데,fruit
컬럼의 값이 apple
또는 banana
또는 orange
와 같다(=
)면 참이라는 뜻이다.
💬 ANY 와 IN의 차이
결론적으로 ANY
는 비교 연산자(>=
, <=
, =
, >
, <
등)와 사용이 가능하고 IN
은 그렇지 않다는 것이다.
이 것 외엔 여러 값을 하나의 컬럼 값과 비교한다는 점에서 거의 유사하다고 할 수 있다.
ANY
예제
SELECT
title, category_id
FROM
film
INNER JOIN
film_category
USING(film_id)
WHERE
category_id = ANY(
SELECT
category_id
FROM
category
WHERE
NAME = 'Action'
OR
NAME = 'Drama'
);
IN
예제
SELECT
title, category_id
FROM
film
INNER JOIN
film_category
USING(film_id)
WHERE
category_id IN(
SELECT
category_id
FROM
category
WHERE
NAME = 'Action'
OR
NAME = 'Drama'
);
https://www.postgresqltutorial.com/postgresql-any/
https://stackoverflow.com/questions/34627026/in-vs-any-operator-in-postgresql
IN vs ANY operator in PostgreSQL
What is the difference between IN and ANY operator in PostgreSQL? The working mechanism of both seems to be the same. Can anyone explain this with an example?
stackoverflow.com