가끔 어떤 값들의 집합이 다른 집합에 포함되는지, 겹치는 게 있는지, 완전히 같은지, 아니면 서로의 부분집합인지 확인해야 할 때가 있어. 예를 들면:
- 유저가 특정 카테고리에 접근 권한이 있는지?
- 어떤 상품들이 공통 태그를 가지고 있는지?
- 어떤 배열이 모든 지정된 값을 포함하는지?
이런 문제들은 PostgreSQL의 배열 비교 연산자 =, @>, <@, &&로 해결할 수 있어. 각각의 연산자를 예제와 함께 살펴보자.
= — 배열이 완전히 같은지 비교
이 연산자는 두 배열이 완전히 똑같은지 확인할 때 써. 두 배열의 길이와 요소 순서, 값이 모두 같아야 TRUE가 나와.
예시:
SELECT ARRAY[1, 2, 3] = ARRAY[1, 2, 3] AS are_equal; -- TRUE
SELECT ARRAY[1, 2, 3] = ARRAY[3, 2, 1] AS are_equal; -- FALSE
특징: 요소의 순서가 중요해. [1, 2, 3]은 [3, 2, 1]이랑 다르다고 나와.
@> — 배열이 다른 배열을 포함하는지
이 연산자는 한 배열이 다른 배열의 모든 요소를 포함하는지(순서는 상관없음) 확인해. 찾고 싶은 값들이 전부 들어있는지 체크할 때 자주 써.
예시:
SELECT ARRAY[1, 2, 3] @> ARRAY[1, 2] AS contains; -- TRUE
SELECT ARRAY[1, 2, 3] @> ARRAY[4] AS contains; -- FALSE
유용한 상황: 권한 체크할 때 좋아. 예를 들어, 어떤 역할(role)이 필요한 모든 권한을 갖고 있는지 확인할 때 쓸 수 있어.
<@ — 배열이 다른 배열의 부분집합인지
@>의 반대야. 한 배열이 다른 배열에 완전히 포함되어 있는지 확인해.
예시:
SELECT ARRAY[1, 2] <@ ARRAY[1, 2, 3] AS is_subset; -- TRUE
SELECT ARRAY[4] <@ ARRAY[1, 2, 3] AS is_subset; -- FALSE
유용한 상황: 테이블의 특정 행이 모든 필요한 태그나 카테고리를 갖고 있는지 확인할 때 쓸 수 있어.
&& — 배열이 겹치는지(교집합)
이 연산자는 두 배열이 하나라도 같은 요소를 갖고 있는지 확인해.
예시:
SELECT ARRAY[1, 2, 3] && ARRAY[3, 4, 5] AS intersects; -- TRUE
SELECT ARRAY[1, 2, 3] && ARRAY[6, 7, 8] AS intersects; -- FALSE
유용한 상황: 공통 카테고리나 특징을 가진 상품이나 레코드를 찾을 때 좋아.
데이터 필터링에 연산자 사용하기
이제 이 연산자들을 테이블 데이터 필터링에 써보자. 예를 들어, products라는 테이블에 각 상품의 태그 배열을 담은 tags 컬럼이 있다고 해보자.
products 테이블 예시
| id | name | tags |
|---|---|---|
| 1 | "Product A" | {electronics, sale} |
| 2 | "Product B" | {home, sale} |
| 3 | "Product C" | {electronics, new} |
| 4 | "Product D" | {home, garden} |
electronics 태그가 있는 상품을 찾아보자.
SELECT *
FROM products
WHERE tags @> ARRAY['electronics'];
결과:
| id | name | tags |
|---|---|---|
| 1 | "Product A" | {electronics, sale} |
| 3 | "Product C" | {electronics, new} |
태그가 정확히 {home, sale}인 상품을 찾고 싶어.
SELECT *
FROM products
WHERE tags = ARRAY['home', 'sale'];
결과:
| id | name | tags |
|---|---|---|
| 2 | "Product B" | {home, sale} |
이번엔
{sale, new} 중 하나라도 태그에 있는 상품을 찾아보자.SELECT *
FROM products
WHERE tags && ARRAY['sale', 'new'];
결과:
| id | name | tags |
|---|---|---|
| 1 | "Product A" | {electronics, sale} |
| 2 | "Product B" | {home, sale} |
| 3 | "Product C" | {electronics, new} |
태그가 정확히 {home, garden}으로만 제한된 상품을 찾아보자.
SELECT *
FROM products
WHERE tags <@ ARRAY['home', 'garden'];
결과:
| id | name | tags |
|---|---|---|
| 4 | "Product D" | {home, garden} |
예시: CASE로 리스트 내용 체크하기
배열 비교를 조건문이랑 같이 쓸 수도 있어. 예를 들어, sale 태그가 있으면 "할인", 없으면 "할인 없음"으로 표시하는 쿼리를 만들어보자:
SELECT name,
CASE
WHEN tags @> ARRAY['sale'] THEN '할인'
ELSE '할인 없음'
END AS discount_status
FROM products;
결과:
| name | discount_status |
|---|---|
| "Product A" | 할인 |
| "Product B" | 할인 |
| "Product C" | 할인 없음 |
| "Product D" | 할인 없음 |
흔한 실수와 예방법
실수: = 연산자에서 요소 순서를 잘못 쓴 경우. =는 요소 순서까지 완전히 같아야 해. 순서가 중요하지 않으면 @>나 &&를 써.
실수: 데이터 타입이 안 맞는 경우. 배열끼리 타입이 같아야 해. 예를 들어, ARRAY['1', '2']는 ARRAY[1, 2]랑 다르지. 앞은 문자열 배열, 뒤는 숫자 배열이니까. 비교 전에 항상 타입을 체크해.
실수: 인덱스가 없는 경우. 배열로 자주 필터링한다면 성능을 위해 꼭 GIN 인덱스를 만들어줘.
이런 연산자들을 잘 쓰면 실제 프로젝트에서 자주 나오는 데이터 필터링과 비교를 쉽게 할 수 있어. 예를 들어 상품 태그 분석이나 권한 관리 같은 거 말이야. 잘 활용하면 복잡한 문제도 간단하게 풀고 쿼리 성능도 확 올릴 수 있어!
GO TO FULL VERSION