명령어/DB

[PostgreSQL] FETCH FIRST n ROWS WITH TIES — 동점까지 포함한 Top-N

jykim23 2026. 7. 23. 21:51
반응형

설치·접속: PostgreSQL 설치와 접속

부제: 이벤트 "상위 3명 경품"에서 3위가 동점일 때, 억울하게 잘리는 사람 없이 뽑을 때

SELECT player, score
FROM leaderboard
ORDER BY score DESC
FETCH FIRST 3 ROWS WITH TIES;
 player | score 
--------+-------
 alice  |   100
 bob    |    95
 carol  |    90
 dave   |    90
 erin   |    90
(5 rows)

3명을 요청했는데 5행이 나왔다. FETCH FIRST 3 ROWS WITH TIES는 상위 3행 + ORDER BY 상 마지막 자리(3위, score=90)와 동점인 행을 모두 추가로 반환한다. carol·dave·erin이 전부 90점이라 셋 다 포함됐다. 경품이 걸린 이벤트라면 이게 공정한 처리다.

LIMIT 3은 이걸 못 한다. 정확히 3행에서 잘라버려 동점자를 임의로 탈락시킨다.

SELECT player, score
FROM leaderboard
ORDER BY score DESC
LIMIT 3;
 player | score 
--------+-------
 alice  |   100
 bob    |    95
 carol  |    90
(3 rows)

같은 90점인데 carol만 살아남고 dave·erin은 사라졌다. 정렬이 안정적이지 않으면 다음 실행에서는 carol 대신 dave가 남을 수도 있다 — "왜 저 사람은 빠졌지"류 버그의 전형이다. WITH TIES는 SQL 표준 FETCH 구문에만 있고 LIMIT에는 없다. 대신 WITH TIESORDER BY가 필수이고(동점 기준이 있어야 하니까), SKIP LOCKED와는 함께 못 쓴다.

이렇게도 쓴다

순위 값 자체가 필요하거나 "정확히 상위 3개 순위"만 원하면 rank()로 간다. 3위 동점자가 모두 rank=3을 받는다. (대비: window rank)

SELECT player, score, rank() OVER (ORDER BY score DESC) AS rnk
FROM leaderboard ORDER BY score DESC;
 player | score | rnk 
--------+-------+-----
 alice  |   100 |   1
 bob    |    95 |   2
 carol  |    90 |   3
 dave   |    90 |   3
 erin   |    90 |   3
 frank  |    85 |   6
 ...

여기서 WHERE rnk <= 3으로 감싸면 FETCH WITH TIES와 같은 결과가 나온다. 동점을 건너뛰고 다음 순위를 4로 매기고 싶으면 dense_rank().

 

앞에서 몇 명 건너뛰고 그 지점의 동점까지 포함하려면 OFFSET과 조합한다. (조합: OFFSET)

SELECT player, score FROM leaderboard
ORDER BY score DESC OFFSET 1 ROWS FETCH FIRST 2 ROWS WITH TIES;

 

동점을 무시하고 딱 N행만 원하면 ONLY(= LIMIT n과 동일).

SELECT player, score FROM leaderboard
ORDER BY score DESC FETCH FIRST 3 ROWS ONLY;

 

동점 판정을 여러 컬럼으로 엄격히 하려면 ORDER BY에 tiebreaker를 더 넣는다. 그러면 동점이 줄어 WITH TIES가 정확히 n행에 수렴한다.

SELECT player, score FROM leaderboard
ORDER BY score DESC, player ASC FETCH FIRST 3 ROWS WITH TIES;

경계: "상위 그룹별로 각각 Top-N"처럼 파티션이 끼면 FETCH로는 안 되고 rank()/row_number() 윈도우로 가야 한다. FETCH WITH TIES는 전체 결과의 단일 Top-N에만 적용된다.

반응형