$ man nth-value
NTH_VALUE
ウィンドウ関数区切りの中の n 番目の値を返す。既定のフレームだと n 番目がまだ見えないことがある。
呼び出しの形
NTH_VALUE(式, n) OVER (ORDER BY 式) NTH_VALUE(式, n) OVER (ORDER BY 式 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
つまずきやすいところ
既定のフレームでは n 番目に届くまで NULL です。
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGを明示してください。n 番目が存在しない区切りでは NULL になります。件数を確かめるか
COALESCEで埋めてください。n は 1 から数えます。0 を渡すとエラーになります。
実行例
結果は実際に流したものです。同じ SQL を 自由に打てる画面 で試すと、同じ結果になります。
SELECT busho_id, name, salary, NTH_VALUE(name, 2) OVER (PARTITION BY busho_id ORDER BY salary DESC, shain_id) AS kitei_frame, NTH_VALUE(name, 2) OVER (PARTITION BY busho_id ORDER BY salary DESC, shain_id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS frame_meiji FROM shain ORDER BY busho_id, salary DESC
| busho_id | name | salary | kitei_frame | frame_meiji |
|---|---|---|---|---|
| 1 | 鈴木 | 980000 | NULL | NULL |
| 2 | 佐藤 | 720000 | NULL | 中村 |
| 2 | 中村 | 530000 | 中村 | 中村 |
| 2 | 田中 | 520000 | 中村 | 中村 |
| 2 | 小林 | 445050 | 中村 | 中村 |
| 3 | 山田 | 700000 | NULL | 伊藤 |
| 3 | 伊藤 | 530000 | 伊藤 | 伊藤 |
| 3 | 高橋 | 480000 | 伊藤 | 伊藤 |
18 行(うち 8 行を表示)
左の列は 1 行目でまだ 2 番目が見えていないので NULL です。右が意図した結果です。
SELECT DISTINCT busho_id, NTH_VALUE(name, 2) OVER (PARTITION BY busho_id ORDER BY salary DESC, shain_id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS ni_banme FROM shain ORDER BY busho_id
| busho_id | ni_banme |
|---|---|
| 1 | NULL |
| 2 | 中村 |
| 3 | 伊藤 |
| 4 | 山本 |
| 5 | 吉田 |
| 7 | 木村 |
| NULL | 渡辺 |
7 行
1 人しかいない部署では 2 番目がないので NULL です。
説明
NTH_VALUE(式, n) は、区切りの中の n 番目の行の値を返します。n は 1 から数えます。
⚠️ 既定のフレームでは、n 番目に到達するまで NULL が返ります。ORDER BY を書くとフレームの既定が「最初から現在行まで」になるためで、1 行目では 2 番目がまだ見えていません。LAST_VALUE と同じ落とし穴です。
区切り全体の n 番目がほしいなら、フレームを明示してください。
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
「2 位の値を全行に並べたい」「上位 3 件と比べたい」といった集計でよく使います。n 番目が存在しないときは NULL になるので、COALESCE で埋めるか、件数を確かめてから使ってください。
次に読む
根拠にした一次情報
- PostgreSQL 18 マニュアル: ウィンドウ関数(2026-09-02 確認)