$ man row-number
ROW_NUMBER
ウィンドウ関数並べた順に 1, 2, 3 … と通し番号を振る。同じ値でも必ず別の番号になる。
呼び出しの形
ROW_NUMBER() OVER (ORDER BY 式) ROW_NUMBER() OVER (PARTITION BY 式 ORDER BY 式)
つまずきやすいところ
同じ値でも別の番号になります。同順位を同じ番号にしたいなら
RANKです。ORDER BYに一意になる列を足さないと、同じ値どうしの順番が実行のたびに変わりえます。結果を再現したいなら必ず足してください。WHEREの中でROW_NUMBER()を直接使うことはできません。ウィンドウ関数はWHEREより後に評価されるためで、副問い合わせやWITHで一度列にしてから絞ります。
実行例
結果は実際に流したものです。同じ SQL を 自由に打てる画面 で試すと、同じ結果になります。
SELECT name, salary, ROW_NUMBER() OVER (ORDER BY salary DESC, shain_id) AS bangou FROM shain ORDER BY bangou
| name | salary | bangou |
|---|---|---|
| 鈴木 | 980000 | 1 |
| 佐藤 | 720000 | 2 |
| 山田 | 700000 | 3 |
| 清水 | 650000 | 4 |
| 加藤 | 610000 | 5 |
| 中村 | 530000 | 6 |
| 伊藤 | 530000 | 7 |
| 田中 | 520000 | 8 |
18 行(うち 8 行を表示)
中村と伊藤は同額(530000)ですが、ROW_NUMBER なので別の番号になります。
SELECT busho_id, name, salary, ROW_NUMBER() OVER (PARTITION BY busho_id ORDER BY salary DESC, shain_id) AS junban FROM shain ORDER BY busho_id, junban
| busho_id | name | salary | junban |
|---|---|---|---|
| 1 | 鈴木 | 980000 | 1 |
| 2 | 佐藤 | 720000 | 1 |
| 2 | 中村 | 530000 | 2 |
| 2 | 田中 | 520000 | 3 |
| 2 | 小林 | 445050 | 4 |
| 3 | 山田 | 700000 | 1 |
| 3 | 伊藤 | 530000 | 2 |
| 3 | 高橋 | 480000 | 3 |
18 行(うち 8 行を表示)
説明
ROW_NUMBER は、ORDER BY で並べた順に重複しない通し番号を振ります。RANK と違い、同じ値でも同じ番号にはなりません。
PARTITION BY を付けると、その区切りごとに 1 から振り直します。「部署ごとに給与の高い順で 1 番、2 番…」といった使い方です。
⚠️ 同じ値が並んでいるとき、どちらが先になるかは決まりません。毎回同じ結果にしたいなら、ORDER BY salary DESC, shain_id のように必ず一意になる列を最後に足してください。これを忘れると、同じ問い合わせなのに実行のたびに順番が変わることがあります。
「各グループの先頭 n 件」を取るときは、ROW_NUMBER を副問い合わせで振ってから外側で WHERE 番号 <= n と絞るのが定石です。
ほかの製品でも通るか
主要 7 製品で通用 そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database / IBM Db2
次に読む
根拠にした一次情報
- PostgreSQL 18 マニュアル: ウィンドウ関数(2026-09-02 確認)