5

私がいくつかのSELECT声明を持っているとしましょう:

SELECT id, name FROM people
   ORDER BY name ASC;

peopleテーブルには数百万の行があり、ORDER BY句はここで示したものよりもはるかに複雑になる可能性があります (12 の列を操作する可能性があります)。

UI に表示するために、行の小さなサブセット (行 1..11 など) のみを取得します。今、私は次の問題を解決したいと思います:

  1. 指定された の行の番号を見つけますid
  2. 指定された の行の前の 5 項目と後の 5 項目を表示しidます。

問題 1 を解決したら、問題 2 は簡単に解決できます。探していたアイテムが1000ソートされた結果セットに行番号を持っていることがわかっている場合は、次のようなものを使用できます (これは Firebird SQL ダイアレクトです)。

SELECT id, name FROM people
   ORDER BY name ASC
   ROWS 995 TO 1005;

また、探している行の前にあるすべての行を数えることで行のランクを見つけることができることも知っていますが、これにより、多数の条件付きWHEREの句が非常に長くなる可能性がORありANDます。そして、私はこれを繰り返し行わなければなりません。私のテスト データでは、適切にインデックス付けされた列を使用している場合でも、数百ミリ秒かかるため、遅すぎます。

いくつかの SQL:2003 機能 ( row_numberFirebird 3.0 でサポートされているものなど) を使用してこれを達成する手段はありますか? 私は SQL の第一人者ではありません。ここでいくつかの指針が必要です。結果にランク/密ランク/行インデックスが含まれるキャッシュ ビューを作成できますか?

4

1 に答える 1

3

Firebird はウィンドウ関数 (Oracle では分析関数と呼ばれます) をサポートしているようです。したがって、次のことができます。

指定された ID を持つ行の「行」番号を見つけるには:

select id, row_number() over (partition by NULL order by name, id)
from t
where id = <id>

これは、ID が一意であることを前提としています。

2 番目の問題を解決するには:

select t.*
from (select id, row_number() over (partition by NULL order by name, id) as rownum
      from t
     ) t join 
     (select id, row_number() over (partition by NULL order by name, id) as rownum
      from t
      where id = <id>
     ) tid
     on t.rownum between tid.rownum - 5 and tid.rownum + 5

ただし、テーブル構造を変更できる場合は、別のことをお勧めします。ほとんどのデータベースでは、行の挿入時に自動インクリメント列を追加する機能が提供されています。レコードが削除されない場合は、これがカウンターとして機能し、クエリが簡素化されます。

于 2012-05-22T13:26:58.293 に答える