web-dev-qa-db-ja.com

DB2のLIMITと同等

DB2 for iSeriesでLIMITをどのように行いますか?

50,000を超えるレコードを持つテーブルがあり、レコード0〜10,000、およびレコード10,000〜20,000を返します。

SQLでは、0〜10,000の場合はクエリの最後にLIMIT 0,10000を、10000〜20,000の場合はクエリの最後にLIMIT 10000,10000を記述します。

それで、これはDB2でどのように行われますか?コードと構文は何ですか? (完全なクエリの例は歓迎されます)

84
elcool

この方法を開発しました:

注文可能な一意の値を持つテーブルが必要です。

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
12
elcool

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;
133
Joe

最近、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

8
Kevin Adler

ここに私が思いついた解決策があります:

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

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

5
Tom Barron

@ elcool's solution は賢明なアイデアですが、行の総数を知る必要があります(クエリの実行中に変更される可能性もあります!)。そこで、残念ながら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

ここで、{last}は必要な最後のレコードの行番号に置き換え、{length}last row - first row + 1として計算された必要な行数に置き換える必要があります。

例えば。 10〜25行(合計16行)が必要な場合、{last}は25で、{length}は25-10 + 1 = 16になります。

2
bluish

OPTIMIZE FOR n ROWS句も検討する必要があります。 SELECTステートメントを制限するためのガイドライン トピックのDB2 LUWドキュメントで、これらすべての詳細を確認できます。

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

これを試して

SELECT * FROM
    (
        SELECT T.*, ROW_NUMBER() OVER() R FROM TABLE T
    )
    WHERE R BETWEEN 10000 AND 20000
1
Lucio Menci

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
gregphplab

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

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.  
0
Hector