PR

【SQL】ROW_NUMBER関数(連番付与)の使い方を3分で解説

Database

ROW_NUMBER()は、SQLのwindow関数の1つ。ROW_NUMBER関数を使用すると、結果セットの行に一意の連番を付与することができます。実際のデータには影響を与えませんが、結果として表示されるデータに番号を付けるのに便利です。

SELECT ROW_NUMBER() OVER() as rownum, *
FROM sample_data;

参考 SELECT文の基本

  • ROW_NUMBER()は、結果セットの行に連番を付与する関数。
  • ORDER BYを使って、特定の順序で番号を付けることが可能。
  • PARTITION BYを使うと、指定した列の値ごとに番号付けをリセットすることができる。

参考 window関数とは?

このページではROW_NUMBER関数の基本を1からわかりやすく初心者向けに解説します。

このページで学べる内容
  • ROW_NUMBER関数の意味と使い方:構文ルール
  • ROW_NUMBER関数の利用方法:サンプルコード

プログラマーやシステムエンジニアを目指す方であれば知らないと恥ずかしい基本知識です。是非最後までご覧ください。

参考 【初心者向け】SQLの基本構文ルール

スポンサーリンク

ROW_NUMBER関数とは?

ROW_NUMBER()はSQLのウィンドウ関数の1つで、データセットの各行に一意の連続する番号(行番号)を付与するときに使用します。主に、行に番号をつけたい場面や特定の条件でのランキングをつけたい場面などで使用されます。

実際のデータに変更を加えるわけではなく、クエリの結果として表示されるデータに一時的に番号を付けるためのものです。

ROW_NUMBER関数:構文ルール

ROW_NUMBER() OVER (
    [PARTITION BY 列名1, 列名2, ... ]
    [ORDER BY 列名A [ASC | DESC], ... ]
)
  • PARTITION BY
    • オプション(任意):特定の列を基にしてデータをグループ分けし、そのグループごとに行番号を1から付け直します。
  • ORDER BY
    • オプション(任意):行番号を付与する際の順序を指定するためのもので、指定した列の順に従って行番号が付与されます。

サンプルコード1 studentsテーブル

/* サンプルデータ
|----|---------|-------|
| id | name    | score |
|----|---------|-------|
| 1  | Alice   | 85    |
| 2  | Bob     | 90    |
| 3  | Charlie | 85    |
| 4  | David   | 92    |
| 5  | Eve     | 88    |
|----|---------|-------|
*/

SELECT 
    ROW_NUMBER() OVER(ORDER BY score, name) as rownum,
    id, 
    name, 
    score
FROM students;

/* 実行結果
scoreの昇順(低いスコアから高いスコアへ)に基づいて行番号が付与された結果が得られる
|--------|----|---------|-------|
| rownum | id | name    | score |
|--------|----|---------|-------|
| 1      | 1  | Alice   | 85    |
| 2      | 3  | Charlie | 85    |
| 3      | 5  | Eve     | 88    |
| 4      | 2  | Bob     | 90    |
| 5      | 4  | David   | 92    |
|--------|----|---------|-------|
*/

サンプルコード2 employeesテーブル

/* 
サンプルデータ: employees
|----|---------|------------|--------|
| id | name    | department | salary |
|----|---------|------------|--------|
| 1  | Alice   | HR         | 5000   |
| 2  | Bob     | Sales      | 5500   |
| 3  | Charlie | HR         | 5200   |
| 4  | David   | Sales      | 5300   |
| 5  | Eve     | Sales      | 6000   |
|----|---------|------------|--------|
*/

-- 部署(department)ごとに給与(salary)の昇順で行番号を付けるクエリ
SELECT 
    ROW_NUMBER() OVER(PARTITION BY department ORDER BY salary) as rownum,
    id, 
    name,
    department,
    salary
FROM employees;

/* 実行結果
|--------|----|---------|------------|--------|
| rownum | id | name    | department | salary |
|--------|----|---------|------------|--------|
| 1      | 1  | Alice   | HR         | 5000   |
| 2      | 3  | Charlie | HR         | 5200   |
| 1      | 4  | David   | Sales      | 5300   |
| 2      | 2  | Bob     | Sales      | 5500   |
| 3      | 5  | Eve     | Sales      | 6000   |
|--------|----|---------|------------|--------|
*/

このクエリの実行結果を見ると、PARTITION BYの効果により、部署ごとに行番号が1から始まっています。そして、その中でORDER BYにより給与の昇順に行番号が付けられていることがわかります。

このように、PARTITION BYORDER BYを組み合わせることで、特定のカテゴリやグループ内での順序付けを行うことができます。

ROW_NUMBER関数を利用する際の注意点

最後にROW_NUMBER関数を利用する際の注意点について補足しておきます。

この関数はよく利用する関数でもあるので、特に以下の点を押さえておくことが重要です。

1. 一意性の確保

ROW_NUMBER()関数は、指定した順序で行に一意の番号を付与します。しかし、同じ値を持つ行(つまり順序が同じ行)が複数存在する場合、それらの行の順序はデータベースエンジンに依存するため、必ずしも一定ではありません。

/* サンプルデータ: students
|----|---------|-------|
| id | name    | score |
|----|---------|-------|
| 1  | Alice   | 85    |
| 2  | Bob     | 85    |
| 3  | Charlie | 90    |
|----|---------|-------|
*/

SELECT 
    ROW_NUMBER() OVER(ORDER BY score) as rownum,
    id, 
    name, 
    score
FROM students;

/* 実行結果 (順序は不確定)
|--------|----|---------|-------|
| rownum | id | name    | score |
|--------|----|---------|-------|
| 1      | ?  | ?       | 85    |
| 2      | ?  | ?       | 85    |
| 3      | 3  | Charlie | 90    |
|--------|----|---------|-------|
*/

このクエリでは、AliceとBobのscoreが同じであるため、それらに付与される行番号の順序は不確定です。

一意の順序を確保するためには、ORDER BY句に複数の列を追加することで、一意性を強制することができます。以下のように、scoreの後にidを追加してみます。

/* サンプルデータ: students
|----|---------|-------|
| id | name    | score |
|----|---------|-------|
| 1  | Alice   | 85    |
| 2  | Bob     | 85    |
| 3  | Charlie | 90    |
|----|---------|-------|
*/

SELECT 
    ROW_NUMBER() OVER(ORDER BY score, id) as rownum,
    id, 
    name, 
    score
FROM students;

/* 実行結果 (一意の順序が確保される)
|--------|----|---------|-------|
| rownum | id | name    | score |
|--------|----|---------|-------|
| 1      | 1  | Alice   | 85    |
| 2      | 2  | Bob     | 85    |
| 3      | 3  | Charlie | 90    |
|--------|----|---------|-------|
*/

このクエリでは、scoreが同じ場合、次にidの順番を考慮するため、一意の順序が確保されます。

2. 性能に関する注意点

大量のデータを扱う場合、ROW_NUMBER()関数の計算には時間がかかることがあります。特にPARTITION BYORDER BYを使った複雑なソートや分割を行う際には、パフォーマンスの低下が考えられます。

適切なインデックスの作成やクエリの最適化を検討することが重要です。

3. ROW_NUMBER() vs RANK() vs DENSE_RANK()

ROW_NUMBER()以外にも、RANK()DENSE_RANK()などの関数があります。これらの関数も行に番号を付与するのに使用されますが、同じ値を持つ行に対する取り扱いが異なります。

使用する関数を選択する際には、それぞれの動作を理解して、目的に合った関数を選択することが重要です。

4. バージョンやデータベースの種類による違い

ROW_NUMBER()関数は、多くのリレーショナルデータベースシステムでサポートされていますが、使用できるバージョンや具体的な動作、性能などにはデータベースの種類やバージョンによる違いがあります。

公式のドキュメントやリファレンスを確認することをおすすめします。

ROW_NUMBER関数のまとめ

  • ROW_NUMBER()は、結果セットの行に連番を付与する関数です。
  • ORDER BYを使って、特定の順序で番号を付けることができます。
  • PARTITION BYを使うと、指定した列の値ごとに番号付けをリセットすることができます。

現在のスキルに今一つ満足できていないシステムエンジニア/プログラマーの方へ。

SQLやデータベースの仕組みを1から学習したい方(学び直したい方)向けに、現役エンジニア達のスキルを結集して 完全無料 のSQL教材を作成しました。是非この機会にブックマークを!

読者料典 【完全無料】SQL:初心者向け学習ロードマップ ←こちらから!

このWebサイトは現役のエンジニアが以下3点を目的として運営しています。

  1. 勉強:一度理解した内容を忘れないように。
    → アウトプットは「最強のインプット」である! 
  2. 備忘:忘れたとしても後から見返せるように。
    → 未来の自分への「お手紙」を書いています。 
  3. 共有:〇〇ってこうだったんだ!の感動をシェアできるように。
    → あなたの知識は誰かにとっての「価値ある情報」です。 

副業ブログの始め方はこちらから

スポンサーリンク
DatabaseIT-Skills
シェアする
ビズドットオンラインをフォローする
タイトルとURLをコピーしました