STRING_AGG로 간결한 쿼리 결과 만들기

SQL의 string_agg 함수는 여러 행의 문자열을 다양한 옵션을 사용하여 하나의 문자열로 연결(합치기)하는 집계 함수입니다.

보고서에서 데이터 그룹별로 열의 값을 결합하고 싶을 때 특히 유용하며, 특히 다대다(many-to-many) 관계를 다룰 때 쿼리 결과를 더 읽기 쉽게 만들어 줍니다. 예를 들어, 각 주제에서 사용된 모든 태그를 표시하는 보고서를 만들려면 string_agg를 사용하여 각 주제별 모든 태그를 하나의 문자열로 연결할 수 있습니다.

구문

string_agg의 기본 구문은 다음과 같습니다:

STRING_AGG(expression, delimiter)

string_agg 함수는 두 가지 매개변수를 받습니다:

  • expression: 연결할 값.
  • delimiter: 문자열 사이에 삽입할 구분자. 구분자는 문자열 또는 문자일 수 있습니다.

DE 쿼리에서의 사용 예시

string_agg를 사용하는 몇 가지 예제 쿼리를 살펴보겠습니다.

사이트의 모든 카테고리 나열

이 쿼리는 categories 테이블의 name과 id 필드를 하나의 문자열로 연결하며, 각 name과 id 쌍은 ’ : ’로, 각 쌍은 ', '로 구분됩니다. 쌍은 id 기준으로 정렬됩니다.

SELECT  
    -- STRING_AGG 함수는 'name'과 'id' 필드를 하나의 문자열로 연결합니다.
    -- 각 'name'과 'id' 쌍은 ' : '로, 각 쌍은 ', '로 구분됩니다.
    -- 쌍은 'id' 기준으로 정렬됩니다.
    STRING_AGG(name || ' : ' || id, ', ' ORDER BY id) AS category_list
FROM 
    categories -- 데이터는 'categories' 테이블에서 선택됩니다.

예시 결과:

category_list
Uncategorized : 1, Site Feedback : 2, Staff : 3, Lounge : 4, Email : 5, Event : 6, Parent Category : 7, Sub Category

모든 주제와 관련 태그 나열

이 쿼리는 topics 테이블에서 id를 선택하고 각 주제에 관련되는 tags를 하나의 문자열로 연결합니다. 각 태그는 쉼표와 공백으로 구분되며, 태그는 알파벳 순으로 정렬됩니다. 결과는 주제의 id별로 그룹화되고 태그 기준으로 정렬됩니다. 주제에 태그가 없으면 tags 열은 NULL이 됩니다.

SELECT t.id topic_id,
    string_agg(tags.name, ', ' ORDER BY tags.name) AS "tags"
FROM topics t
LEFT JOIN topic_tags tt ON tt.topic_id = t.id
LEFT JOIN tags ON tags.id = tt.tag_id
GROUP BY t.id   
ORDER BY tags

결과는 알파벳 순으로 정렬된 관련 태그 문자열이 포함된 형식화된 주제 ID 목록이 됩니다. 예를 들어:

예시 결과:

topic tags
Welcome to the Lounge (3) tag1, tag2
A Very Safe for work post (3) tag3, tag4, tag,5
This is a blog tagged post (4) tag3
About the Lounge category (3) tag5
Welcome to your 14 day standard hosting trial! NULL
인라인 주석이 포함된 상세 설명
-- 이 SQL 문장은 'topics' 테이블과 관련 'tags'에서 데이터를 선택합니다.
SELECT 
    t.id topic_id, -- 'topics' 테이블에서 'id'를 선택합니다.
    -- STRING_AGG 함수는 각 주제에 관련되는 'tags'를 하나의 문자열로 연결합니다.
    -- 각 태그는 쉼표와 공백으로 구분되며, 태그는 알파벳 순으로 정렬됩니다.
    string_agg(tags.name, ', ' ORDER BY tags.name) AS "tags"
FROM 
    topics t -- 데이터는 'topics' 테이블에서 선택됩니다.
    -- 'topic_tags' 테이블은 'topics' 테이블의 'topic_id'와 왼쪽 조인됩니다.
    LEFT JOIN topic_tags tt ON tt.topic_id = t.id
    -- 'tags' 테이블은 'topic_tags' 테이블의 'tag_id'와 왼쪽 조인됩니다.
    LEFT JOIN tags ON tags.id = tt.tag_id
GROUP BY 
    t.id -- 결과는 주제의 'id'별로 그룹화됩니다.
ORDER BY
    "tags" -- 결과는 'tags' 기준으로 정렬됩니다.

주제에 게시한 사용자

이 쿼리는 topic id와 titles, 각 주제에 게시한 사용자의 usernames, 그리고 각 주제에 게시한 고유 사용자 수(count of distinct users) 목록을 반환합니다. 결과는 사용자 수 기준으로 내림차순 정렬됩니다.

SELECT
    topics.id AS "topic_id",
    topics.title AS "topic_title",
    STRING_AGG(DISTINCT users.username, ', ' ORDER BY users.username) AS "users_posted",
    COUNT(DISTINCT users.id) AS "user_count"
FROM
    topics
JOIN
    posts ON posts.topic_id = topics.id
JOIN
    users ON users.id = posts.user_id
GROUP BY
    topics.id, topics.title
ORDER BY
    "user_count" DESC

예시 결과

topic topic_title users_posted user_count
Lets make a topic (10) Lets make a topic anonymous, user1, user2, user3 4
Another Topic (3) Another Topic user3, user4, user5 3
Discobot test (2) Discobot test user6 1
인라인 주석이 포함된 상세 설명
-- 이 SQL 문장은 'topics', 'posts', 'users' 테이블에서 데이터를 선택합니다.
SELECT
    topics.id AS "topic_id", -- 'topics' 테이블에서 'id'를 선택합니다.
    topics.title AS "topic_title", -- 'topics' 테이블에서 'title'을 선택합니다.
    -- STRING_AGG 함수는 주제에 게시한 사용자의 사용자명을 하나의 문자열로 연결합니다.
    -- 각 사용자명은 쉼표와 공백으로 구분되며, 사용자명은 알파벳 순으로 정렬됩니다.
    STRING_AGG(DISTINCT users.username, ', ' ORDER BY users.username) AS "users_posted",
    -- 주제에 게시한 고유 사용자의 수를 계산합니다.
    COUNT(DISTINCT users.id) AS "user_count"
FROM
    topics -- 데이터는 'topics' 테이블에서 선택됩니다.
    -- 'posts' 테이블은 'topics' 테이블의 'topic_id'와 조인됩니다.
    JOIN posts ON posts.topic_id = topics.id
    -- 'users' 테이블은 'posts' 테이블의 'id'와 조인됩니다.
    JOIN users ON users.id = posts.user_id
GROUP BY
    topics.id, topics.title -- 결과는 주제의 'id'와 'title'별로 그룹화됩니다.
ORDER BY
    "user_count" DESC -- 결과는 사용자 수 기준으로 내림차순 정렬됩니다.

이 튜토리얼은 여기서 끝입니다!

string_agg에 대한 질문이나 사용 예시가 있다면 아래에 자유롭게 공유해 주세요. :slightly_smiling_face:

6개의 좋아요