Zend Framework のデータベース コンポーネントに取り組んだときLIMIT
、MySQL、PostgreSQL、および SQLite でサポートされている句の機能を抽象化しようとしました。つまり、クエリの作成は次の方法で行うことができます。
$select = $db->select();
$select->from('mytable');
$select->order('somecolumn');
$select->limit(10, 20);
データベースが をサポートしている場合LIMIT
、次のような SQL クエリが生成されます。
SELECT * FROM mytable ORDER BY somecolumn LIMIT 10, 20
これは、サポートしていないブランドのデータベースではより複雑でしたLIMIT
(ちなみに、その節は標準 SQL 言語の一部ではありません)。行番号を生成できる場合は、クエリ全体を派生テーブルにし、外側のクエリで を使用しますBETWEEN
。これは、Oracle および IBM DB2 のソリューションでした。Microsoft SQL Server 2005 には同様の行番号関数があるため、次のようにクエリを記述できます。
SELECT z2.*
FROM (
SELECT ROW_NUMBER OVER(ORDER BY id) AS zend_db_rownum, z1.*
FROM ( ...original SQL query... ) z1
) z2
WHERE z2.zend_db_rownum BETWEEN @offset+1 AND @offset+@count;
ただし、Microsoft SQL Server 2000 にはその機能がありませんROW_NUMBER()
。
LIMIT
私の質問は、 SQL のみを使用して、Microsoft SQL Server 2000の機能をエミュレートする方法を思い付くことができるかということです。カーソル、T-SQL、またはストアド プロシージャを使用しない場合。の両方の引数LIMIT
、カウントとオフセットの両方をサポートする必要があります。一時テーブルを使用したソリューションも受け入れられません。
編集:
MS SQL Server 2000 の最も一般的な解決策は、たとえば行 50 から 75 を取得する、次のようなものです。
SELECT TOP 25 *
FROM (
SELECT TOP 75 *
FROM table
ORDER BY BY field ASC
) a
ORDER BY field DESC;
ただし、結果セットの合計が 60 行の場合、これは機能しません。内側のクエリは 60 行を返します。これは上位 75 行に含まれているためです。その後、外側のクエリは行 35 ~ 60 を返しますが、これは 50 ~ 75 の目的の「ページ」に収まりません。基本的に、このソリューションは、たまたまページ サイズの倍数ではない結果セットの最後の「ページ」が必要でない限り機能します。
編集:
別の解決策はより適切に機能しますが、結果セットに一意の列が含まれていると想定できる場合に限ります。
SELECT TOP n *
FROM tablename
WHERE key NOT IN (
SELECT TOP x key
FROM tablename
ORDER BY key
);
結論:
MS SQL Server 2000でエミュレートするための汎用ソリューションは存在しないようです。MS SQL Server 2005 でLIMIT
この機能を使用できる場合、適切なソリューションが存在します。ROW_NUMBER()