【SQL】ROW_NUMBER()でグループごとの連番を取得する【SQL Server】

  • 2020.08.21
  • SQL
【SQL】ROW_NUMBER()でグループごとの連番を取得する【SQL Server】

はじめに

コジマです。

例えば画面に表示されているデータをID順に連番を振りなおしたい場合なんかに使います。

シチュエーション

本の発注履歴を外部システムに連携したいとします。
こちらのシステムでは画面から登録した表示順にデータを管理していますが、
外部システムでは本のID順に表示順を登録しなおさないといけません。
こんな場合を想定して本記事で例を書き進めます。

/* 発注した本のデータ */
WITH order_books AS (
    SELECT 1 as book_id, 0 as sort_no
    UNION
    SELECT 3 as book_id, 1 as sort_no
    UNION
    SELECT 7 as book_id, 2 as sort_no
    UNION
    SELECT 2 as book_id, 3 as sort_no
    UNION
    SELECT 5 as book_id, 4 as sort_no
)
/* 本のマスタデータ */
, books AS (
    SELECT 1 as book_id, N'情弱を騙して儲ける本' as book_name
    UNION
    SELECT 2 as book_id, N'未経験からたった3か月でフリーランスになる本' as book_name
    UNION
    SELECT 3 as book_id, N'未経験から半年でAIエンジニアになる本' as book_name
    UNION
    SELECT 4 as book_id, N'スマホ一つでスキマ時間で稼ぐ本' as book_name
    UNION
    SELECT 5 as book_id, N'楽して稼ぐ10のコツ' as book_name
    UNION
    SELECT 6 as book_id, N'誰でもできるFX' as book_name
    UNION
    SELECT 7 as book_id, N'人脈こそパワー' as book_name
    UNION
    SELECT 8 as book_id, N'情弱を騙して儲ける本に騙される情弱にならない方法' as book_name
)
SELECT
    ob.book_id
    , b.book_name
    , ob.sort_no
FROM order_books ob
JOIN books b ON ob.book_id = b.book_id
ORDER BY book_id

出力結果

book_id book_name sort_no
1 情弱を騙して儲ける本 1
2 未経験からたった3か月でフリーランスになる本 4
3 未経験から半年でAIエンジニアになる本 2
5 楽して稼ぐ10のコツ 5
7 人脈こそパワー 3

本のID順に並べると表示順がぐちゃぐちゃになってしまいますね。
こういう時役立つのがROW_NUMBER() です。

ROW_NUMBER()を使う例

/* 発注した本のデータ */
WITH order_books AS (
    SELECT 1 as book_id, 1 as sort_no
    UNION
    SELECT 3 as book_id, 2 as sort_no
    UNION
    SELECT 7 as book_id, 3 as sort_no
    UNION
    SELECT 2 as book_id, 4 as sort_no
    UNION
    SELECT 5 as book_id, 5 as sort_no
)
/* 本のマスタデータ */
, books AS (
    SELECT 1 as book_id, N'情弱を騙して儲ける本' as book_name
    UNION
    SELECT 2 as book_id, N'未経験からたった3か月でフリーランスになる本' as book_name
    UNION
    SELECT 3 as book_id, N'未経験から半年でAIエンジニアになる本' as book_name
    UNION
    SELECT 4 as book_id, N'スマホ一つでスキマ時間で稼ぐ本' as book_name
    UNION
    SELECT 5 as book_id, N'楽して稼ぐ10のコツ' as book_name
    UNION
    SELECT 6 as book_id, N'誰でもできるFX' as book_name
    UNION
    SELECT 7 as book_id, N'人脈こそパワー' as book_name
    UNION
    SELECT 8 as book_id, N'情弱を騙して儲ける本に騙される情弱にならない方法' as book_name
)
SELECT
    ob.book_id
    , b.book_name
    , ob.sort_no
    -- 本のID順に連番を取得
    , ROW_NUMBER() OVER (ORDER BY ob.book_id) as new_sort_no
FROM order_books ob
JOIN books b ON ob.book_id = b.book_id
ORDER BY book_id

出力結果

book_id book_name sort_no new_sort_no
1 情弱を騙して儲ける本 1 1
2 未経験からたった3か月でフリーランスになる本 4 2
3 未経験から半年でAIエンジニアになる本 2 3
5 楽して稼ぐ10のコツ 5 4
7 人脈こそパワー 3 5

PARTITION BYを組み合わせることで、発注IDごとに連番を振るなんてこともできます。

/* 発注した本のデータ */
WITH order_books AS (
    SELECT 1 as order_id, 1 as book_id, 1 as sort_no
    UNION
    SELECT 1 as order_id, 3 as book_id, 2 as sort_no
    UNION
    SELECT 2 as order_id, 7 as book_id, 1 as sort_no
    UNION
    SELECT 2 as order_id, 2 as book_id, 2 as sort_no
    UNION
    SELECT 2 as order_id, 5 as book_id, 3 as sort_no
)
/* 本のマスタデータ */
, books AS (
    SELECT 1 as book_id, N'情弱を騙して儲ける本' as book_name
    UNION
    SELECT 2 as book_id, N'未経験からたった3か月でフリーランスになる本' as book_name
    UNION
    SELECT 3 as book_id, N'未経験から半年でAIエンジニアになる本' as book_name
    UNION
    SELECT 4 as book_id, N'スマホ一つでスキマ時間で稼ぐ本' as book_name
    UNION
    SELECT 5 as book_id, N'楽して稼ぐ10のコツ' as book_name
    UNION
    SELECT 6 as book_id, N'誰でもできるFX' as book_name
    UNION
    SELECT 7 as book_id, N'人脈こそパワー' as book_name
    UNION
    SELECT 8 as book_id, N'情弱を騙して儲ける本に騙される情弱にならない方法' as book_name
)
SELECT
    ob.order_id
    , ob.book_id
    , b.book_name
    , ob.sort_no
    -- 本のID順に連番を取得
    , ROW_NUMBER() OVER (PARTITION BY ob.order_id ORDER BY ob.book_id) as new_sort_no
FROM order_books ob
JOIN books b ON ob.book_id = b.book_id
ORDER BY ob.order_id, ob.book_id

出力結果

order_id book_id book_name sort_no new_sort_no
1 1 情弱を騙して儲ける本 1 1
1 3 未経験から半年でAIエンジニアになる本 2 2
2 2 未経験からたった3か月でフリーランスになる本 2 1
2 5 楽して稼ぐ10のコツ 3 2
2 2 人脈こそパワー 1 3

使い方を簡単に

ROW_NUMBER() OVER (条件) AS 別名

この構文を覚えておきましょう。

さいごに

ROW_NUMBER()はウインドウ関数と呼ばれるものの一つで、他にもいろいろ種類があります。
ここでは触れませんが、また覚えたものを記事にできればな~と思っている次第です。

この記事を面白いまたは役に立ったと思ってくれた方は是非私のTwitter(@kojimanotech)を
フォローしてくれたらうれしいです!

以上、コジマでした。


SQLカテゴリの最新記事