728x90
※ PostgreSQL: DISTINCT ON.
안녕하세요. 듀스트림입니다.
오늘 포스팅은 PostgreSQL 고유 확장 기능인 DISTINCT ON에 대한 내용입니다.
알아두면 꽤 편합니다.
DISTINCT ON은 표준 ANSI SQL에 속하지 않으며, PostgreSQL 고유 확장 기능입니다.
표준 방식은 ROW_NUMBER()를 사용합니다.
표준 방식
SELECT user_id, event_time, status
FROM (
SELECT
user_id,
event_time,
status,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY event_time DESC) AS rn
FROM user_events
) t
WHERE rn = 1;
DISTINCT ON 사용
SELECT DISTINCT ON (user_id) user_id, event_time, status
FROM user_events
ORDER BY user_id, event_time DESC;
훨씬 간결하죠? 실행계획을 봐도 노드 뎁스가 표준보다 하나 작아서 가독성이 좋습니다.
SELECT
SELECT SELECT, TABLE, WITH — retrieve rows from a table or view Synopsis [ WITH [ RECURSIVE ] with_query [, …
www.postgresql.org
+ 단일 컬럼만 가능하냐는 질문을 받아서 추가 내용 작성합니다.
- DISTINCT ON은 1개의 컬럼만 가능한 게 아니라, 하나의 그룹 키 집합을 여러 컬럼으로 만들 수 있습니다.
- ROW_NUMBER()의 PARTITION BY에 배열된 여러 컬럼도 당연히 쓸 수 있고 콤마로 나열하면 됩니다.
문법은:
SELECT DISTINCT ON (col1, col2, col3, ...)
...
FROM ...
ORDER BY col1, col2, col3, ... , <tie-breakers...>;
- DISTINCT ON (col1, col2) → (col1, col2) 조합이 같은 것들 중 첫 번째 행만 선택
- 첫 번째가 뭔지는 ORDER BY로 결정
- ORDER BY의 맨 앞 컬럼들은 반드시 DISTINCT ON에 있는 컬럼들과 같은 순서여야 함
- 그 뒤에 정렬 컬럼을 붙여서 "대표로 뽑힐 행"을 결정
예시:
-- (user_id, order_date) 기준으로 한 행만 선택하고 싶다.
-- 같은 (user_id, order_date) 안에서 amount가 가장 큰 행을 뽑고 싶다면:
SELECT DISTINCT ON (user_id, order_date)
user_id,
order_date,
amount
FROM orders
ORDER BY user_id, order_date, amount DESC;
- (user_id, order_date)가 같은 행들 중에서 amount DESC 기준으로 가장 큰 행만 남김.
정리
• DISTINCT ON (컬럼1, 컬럼2, ...) 형태로 여러 컬럼 지정 가능
• ORDER BY는 DISTINCT ON 컬럼들 + 대표 행을 고를 정렬 기준까지 함께 적어야 함.
ROW_NUMBER()로 작성하면:
SELECT *
FROM (
SELECT
user_id,
order_date,
amount,
ROW_NUMBER() OVER (
PARTITION BY user_id, order_date
ORDER BY amount DESC
) AS rn
FROM orders
) t
WHERE rn = 1;
- (user_id, order_date) 별로 그룹 나누고, amount DESC 큰 것부터 rn = 1 부여 → 대표 행 선택
비교 표
| 방식 | 그룹 키 정의 | 대표 행 선택 기준 | 특징 |
| DISTINCT ON | DISTINCT ON (c1, c2) | ORDER BY ... | PostgreSQL 전용, 문법 간단 |
| ROW_NUMBER() | PARTITION BY c1, c2 | ORDER BY ... | 표준 SQL, 다른 DB에도 사용 가능 |
오늘은 여기까지~
728x90
'PostgreSQL' 카테고리의 다른 글
| PostgreSQL: Patroni Cluster 사용 시 파라미터 변경 방법 (0) | 2025.12.12 |
|---|---|
| PostgreSQL: SELECT 효율 분석 (0) | 2025.11.21 |
| PostgreSQL: 스트리밍 복제 지연 (0) | 2025.11.12 |
| PostgreSQL: never executed (0) | 2025.11.10 |
| PostgreSQL: ctid (0) | 2025.11.07 |