検索条件の結果行から任意の行のレコードのみを取得する方法を2つ紹介します。
次のようなテーブルを用意して実行結果と合わせて解説していきます。
準備①テーブルを作成
CREATE TABLE sample_tbl
(
objectid bigserial NOT NULL,
col1 character varying,
col2 bigint,
createdate timestamp without time zone,
CONSTRAINT sample_tbl_pkey PRIMARY KEY (objectid)
)
準備②サンプルレコードを用意
【実現方法その1】ROW_NUMBER関数を使う
行番号を付けたうえで、任意の行番号で取得したいレコードを指定する方法です。
まず次のようなSQLで行番号が取得できることが確認できます。
※ROW_NUMBERについて
SELECT ROW_NUMBER() OVER() AS rownum , * FROM sample_tbl;
任意の順番で行番号をつける場合
SELECT ROW_NUMBER() OVER(ORDER BY createdate DESC) AS rownum , * FROM sample_tbl;
それでは、createdateの降順にしたときの2番目のレコードを取得するとしましょう。
SELECT ROW_NUMBER() OVER(ORDER BY createdate DESC) AS rownum , * FROM sample_tbl WHERE rownum = 2;
そのため、サブクエリにする必要があります。
SELECT * FROM
(SELECT ROW_NUMBER() OVER(ORDER BY createdate DESC) AS rownum , * FROM sample_tbl) AS tbl
WHERE tbl.rownum = 2;
【実現方法その2】OFFSETとLIMITを使う
同じようにcreatedateの降順にしたときの2番目のレコードを取得するとしましょう。
次のようなSQLで取得できます。
SELECT * FROM sample_tbl ORDER BY createdate DESC OFFSET 1 LIMIT 1;
LIMITは取得したいレコードの件数なので特に説明は不要だと思います。
OFFSETは開始したい行という意味ではなく、飛ばす行数を意味しているので、注意してください。
2件目以降が欲しい場合は1件だけ飛ばすので「OFFSET 1」となるのです。
詳しい説明はこちら
まとめ
シンプルな要件に対応するのであれば、OFFSET, LIMITの方が簡単だと思いました。
ただし、○件目~○件目までというような範囲指定はどちらも対応できますが、
○件目と○件目と○件目のような複数の任意行を取得する場合はOFFSET, LIMITではなく、ROW_NUMBERを使った方が柔軟に対応できると思います。