こんにちは!
どうも!uenonです。

最近、SQLServerのテーブルからデータを引っ張ってきて
一覧に表示させる画面の設計を行っています。
対象の一覧にページ制御をつけていることが多々あるのですが、
皆様はどうやってページ毎のデータを抽出していますか???
サーバーから一括に全件データを抽出してレコードセットとか配列とかの変数に格納して
その変数からページ毎のデータを抽出するのがサーバーへの接続回数が減って負荷が少ないのでベターかなと思っています。
(私はこのやり方が多かったかな。。。)
ただ最近、SQLでページングする機会があったのでやり方を調べました。
今回ここで調べた結果を書いていきます。
興味がある方は良かったら最後までお付き合いください!

まぁやり方は色々あると思いますが、
今回はROW_NUMBERとOFFSETを使ったやり方を紹介しようと思います。

まずは、ROW_NUMBERのを使ったやり方について
そもそもROW_NUMBERは抽出結果の全ての行にナンバリングするやつですね!
RANKに似てますが、RANKは同順位に対して同じ番号を付けるので違う用途になります。
例えば、同順位のレコードがあってもROW_NUMBERだと1,2,3,4,5になりますが、
RANKだと1,2,2,4,5になってしまいます。

さてさて話は戻ってROW_NUMBER関数で抽出結果に採番した項番を
BETWEENで指定してあげれば抽出結果を制限できるようになります。
以下は1ページ10件の一覧で2ページ目のデータを取得する使用例です。

–testテーブルをcolumn1の順に11件目~20件目のみ取得する
SELECT

 column1
FROM
 (SELECT column1,ROW_NUMBER() OVER (ORDER BY column1) AS rownum FROM test) AS t
WHERE
 rownum BETWEEN 11 AND 20
ORDER BY
 rownum

注意事項としてはそのままWHERE句で絞り込めないので
以下の書き方だとエラーになります。

SELECT
 column1,ROW_NUMBER() OVER (ORDER BY column1) AS rownum
FROM
 test
WHERE
 rownum BETWEEN 11 AND 20
ORDER BY
 rownum

続いて、OFFSETの使ったやり方について
OFFSETを使って1ページ10件の一覧で2ページ目のデータを取得する使用例です。

-testテーブルをcolumn1の順に11件目~20件目のみ取得する
SELECT
 column1
FROM
 test
ORDER BY
 column1
OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY

何をしているのかというと
OFFSET {スキップ行数} ROWS
ここでスキップ行数を指定しています。
そのため1ページ目の10行分を取得しないようにしています。

FETCH NEXT {取得する行数} ROWS ONLY
ここでスキップした行から取得する行数を指定していますので
2ページ目は11~20までを表示させたいので20を指定しています。

と、ここまで2つのやり方を紹介させていただきましたが、
なんでこの2つを紹介したのかというとOFFSETが
SQLServer2012未満のバージョンだと使えないからです。
なので、SQLServer2012未満だとROW_NUMBERでのやり方しかできませんが、
SQLServer2012以上の方はどちらも使えると思いますので
ここまで読まれた方は実装方法の選択肢として
頭の片隅にでもおいていただければと思います。

それでは、 See you next time👉