DBGuide

배열 타입과 연산

📖 약 2🏷 고급 쿼리

배열 타입

PostgreSQL은 모든 데이터 타입의 배열을 지원합니다.

CREATE TABLE articles (
    id       SERIAL PRIMARY KEY,
    title    VARCHAR(300) NOT NULL,
    tags     TEXT[],          -- 문자열 배열
    scores   INT[]            -- 정수 배열
);

INSERT INTO articles (title, tags, scores)
VALUES ('PostgreSQL 입문', ARRAY['database', 'sql', 'postgresql'], ARRAY[95, 87, 92]);

배열 리터럴

-- 두 가지 방식
SELECT ARRAY[1, 2, 3];
SELECT '{1, 2, 3}'::INT[];

-- 2차원 배열
SELECT ARRAY[[1, 2], [3, 4]];

배열 요소 접근 (1-based index)

SELECT tags[1] FROM articles;          -- 첫 번째 태그
SELECT tags[1:2] FROM articles;        -- 슬라이싱 (1~2번째)
SELECT array_length(tags, 1) FROM articles;  -- 배열 길이

배열 검색

-- 특정 값 포함 여부
SELECT * FROM articles WHERE 'sql' = ANY(tags);
SELECT * FROM articles WHERE tags @> ARRAY['sql', 'database'];  -- 모두 포함
SELECT * FROM articles WHERE tags && ARRAY['sql', 'python'];     -- 하나라도 포함

배열 조작 함수

-- 요소 추가
SELECT array_append(ARRAY[1, 2, 3], 4);         -- {1,2,3,4}
SELECT array_prepend(0, ARRAY[1, 2, 3]);         -- {0,1,2,3}
SELECT array_cat(ARRAY[1, 2], ARRAY[3, 4]);      -- {1,2,3,4}

-- 요소 제거
SELECT array_remove(ARRAY[1, 2, 2, 3], 2);      -- {1,3}

-- 배열 → 행으로 변환 (unnest)
SELECT unnest(ARRAY['a', 'b', 'c']) AS element;
-- a
-- b
-- c

집계 → 배열

-- 부서별 직원 이름을 배열로 수집
SELECT
    department,
    array_agg(name ORDER BY name) AS members,
    array_agg(salary)              AS salaries
FROM employees
GROUP BY department;

unnest 활용 — 배열을 테이블처럼

-- 태그별 게시글 수 집계
SELECT
    unnest(tags) AS tag,
    COUNT(*)     AS article_count
FROM articles
GROUP BY tag
ORDER BY article_count DESC;

GIN 인덱스로 배열 검색 가속

CREATE INDEX idx_articles_tags ON articles USING GIN(tags);

-- @>, &&, ANY 연산이 인덱스를 사용하게 됨
SELECT * FROM articles WHERE tags @> ARRAY['postgresql'];

배열은 정규화의 대안이 아닙니다. 배열 요소를 기준으로 JOIN이 필요하다면 별도 테이블로 분리하는 것이 더 적합합니다.

댓글

... 으로 작성됩니다

댓글을 불러오는 중...