DB2のLIMITに相当


91

LIMITDB2 for iSeriesではどのようにしますか?

50,000件を超えるレコードを含むテーブルがあり、0〜10,000件のレコードと10,000〜20,000件のレコードを返したい。

私はSQLにあなたが書い知っ LIMIT 0,1000010,000 0に対するクエリの終わりとLIMIT 10000,1000010000〜20000のクエリの終わりに

では、これはDB2でどのように行われるのでしょうか。コードと構文は何ですか?(完全なクエリの例は高く評価されています)


ROW_NUMBER()は、iSeries DB2 V5R4でのみ実装されました。以前のバージョンでは、同様のRRN()を使用してみてください。
ポールモーガン、

RRN()は、row_number()とは完全に異なります。
ブランドンピーターソン

私にとってはうまくいきませんでした。Sytanxエラー。
elcool

1
行の物理的な相対レコード番号を与えるRRN(filename)を試してください。RRNは順次ではなく、行が削除されている場合は番号をスキップできます。RRNもキーごとに順次ではありませんが、削除が発生しなかった場合は、追加に基づいて順次になります。いずれの場合も、RRNは行に対して一意であり、テーブルのサブセットを選択するために使用できます。
ポールモーガン、

回答:


139

使用FETCH FIRST [n] ROWS ONLY

http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.perf/db2z_fetchfirstnrows.htm

SELECT LASTNAME, FIRSTNAME, EMPNO, SALARY
  FROM EMP
  ORDER BY SALARY DESC
  FETCH FIRST 20 ROWS ONLY;

範囲を取得するには、ROW_NUMBER()(v5r4以降)を使用し、それをWHERE句内で使用する必要があります(ここから盗みます:http : //www.justskins.com/forums/db2-select-how-to-123209.html )

SELECT code, name, address
FROM ( 
  SELECT row_number() OVER ( ORDER BY code ) AS rid, code, name, address
  FROM contacts
  WHERE name LIKE '%Bob%' 
  ) AS t
WHERE t.rid BETWEEN 20 AND 25;

ええ、私もこれを見つけました、へへ。同時に質問を編集して、中央の行も必要であることを示しました。
elcool


ROW_NUMBERは有効なキーワードではありません。しかし、リンクのthx、それは私にアイデアを与え、それは動作します。
elcool

13

このメソッドを開発しました:

注文できる一意の値を持つテーブルが必要です。

行10,000から25,000が必要で、テーブルに40,000行がある場合、最初に開始点と合計行を取得する必要があります。

int start = 40000 - 10000;

int total = 25000 - 10000;

次に、これらをコードでクエリに渡します。

SELECT * FROM 
(SELECT * FROM schema.mytable 
ORDER BY userId DESC fetch first {start} rows only ) AS mini 
ORDER BY mini.userId ASC fetch first {total} rows only

10000行目は結果セットから除外され、1行目は10001行目であることに注意してください。
青みがかった

1
興味深いソリューション。H2テストデータベースとの互換性のために使用しましたが、悲しいことに、SELECT row_number()OVER(ORDER BY code)アプローチよりも約30倍遅く動作します。
マナナ2013

9

最近、OFFSETおよびLIMITのサポートがDB2 for i 7.1および7.2に追加されました。このサポートを受けるには、以下のDB PTFグループレベルが必要です。

  • IBM i 7.2のSF99702レベル9
  • IBM i 7.1のSF99701レベル38

詳細については、こちらを参照してください:OFFSETおよびLIMITの資料、DB2 for i拡張Wiki


7

これが私が思いついた解決策です:

select FIELD from TABLE where FIELD > LASTVAL order by FIELD fetch first N rows only;

LASTVALを0(またはテキストフィールドの場合は '')に初期化し、それを最新のレコードセットの最後の値に設定すると、Nレコードのチャンクでテーブルがステップ実行されます。


(私が最初にあなたがされるであろう、テーブルに値を設定すると思っていた見事にあなたがのいくつかの並べ替えを必要とすると思いますが、はい、これはあなたがテーブルを介してシーケンシャルリードをやっている場合に動作するはず並行システム上の問題)が列内Nの同一値の数よりも小さい場合のタイブレーカー列(これは使用する場合ROW_NUMBER()も同様です)。初期値も慎重に選択する必要があります。0列に負の値が含まれている場合は明らかに問題があります。nullには注意が必要です。ページがスキップされると機能しません。
時計じかけのミューズ

コメントをありがとう。クエリの制御に使用しているフィールドは一意で単調に増加しているという暗黙の仮定があると思います。これらの仮定が成立しない場合、これはテーブル内のすべてのレコードを訪問するためには機能しないことに同意します。そしてもちろん、あなたは理にかなっているLASTVALから始めなければならないことは正しいです。一般的に、「select MINIMUM(FIELD)from TABLE」によって返されるものから始めたいと思います。フィールドにインデックスが付けられている場合、ほとんどのdbエンジンはテーブル全体を順番に読み取るよりも優れています。
Tom Barron

2

@elcoolのソリューションは賢いアイデアですが、行の総数を知る必要があります(クエリの実行中に変更されることもあります!)。だから私は変更されたバージョンを提案しますが、これは残念ながら2つではなく3つのサブクエリを必要とします:

select * from (
    select * from (
        select * from MYLIB.MYTABLE
        order by MYID asc 
        fetch first {last} rows only 
        ) I 
    order by MYID desc
    fetch first {length} rows only
    ) II
order by MYID asc

where {last}は、必要な最後のレコードの行番号で置き換え、必要な行数で{length}置き換えlast row - first row + 1ます。

たとえば、10行から25行(合計16行){last}が必要な場合、25に{length}なり、25-10 + 1 = 16になります。


他の人が質問に答えるのに時間がかかるときに反対票を投じる人は嫌いです。
jp2code

1

OPTIMIZE FOR n ROWS句も検討する必要があります。これらすべての詳細については、DB2 LUWのドキュメントのSELECTステートメントを制限するためガイドラインのトピックを参照してください。

  • OPTIMIZE FOR句は、結果のサブセットのみを取得する、または最初の数行のみを取得することを優先する意図を宣言します。オプティマイザーは、最初の数行を取得するための応答時間を最小限に抑えるアクセスプランを選択できます。


0

DB2テーブルで効率的にページ分割する2つのソリューションがあります。

1-関数row_number()と、別の投稿で提示された句OVERを使用する手法( "SELECT row_number()OVER(ORDER BY ...)")。いくつかの大きなテーブルで、パフォーマンスの低下に気づいたことがあります。

2-スクロール可能なカーソルを使用する手法。実装は、使用する言語によって異なります。この手法は、大きなテーブルではより堅牢に見えます。

来年のセミナーで、PHPに実装された2つのテクニックを紹介しました。スライドは次のリンクから入手できます:http : //gregphplab.com/serendipity/uploads/slides/DB2_PHP_Best_practices.pdf

申し訳ありませんが、このドキュメントはフランス語のみです。


0

これらの利用可能なオプションがあります:-

DB2 has several strategies to cope with this problem.
You can use the "scrollable cursor" in feature.
In this case you can open a cursor and, instead of re-issuing a query you can FETCH forward and backward.
This works great if your application can hold state since it doesn't require DB2 to rerun the query every time.
You can use the ROW_NUMBER() OLAP function to number rows and then return the subset you want.
This is ANSI SQL 
You can use the ROWNUM pseudo columns which does the same as ROW_NUMBER() but is suitable if you have Oracle skills.
You can use LIMIT and OFFSET if you are more leaning to a mySQL or PostgreSQL dialect.  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.