39

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()

4

4 に答える 4

5

以下は、except ステートメントを使用するため、Sql Server 2005 以降でのみ機能する別のソリューションです。しかし、とにかく共有します。レコード 50 ~ 75 を取得する場合は、次のように記述します。

select * from (
    SELECT top 75 COL1, COL2
    FROM MYTABLE order by COL3
) as foo
except
select * from (
    SELECT top 50 COL1, COL2
    FROM MYTABLE order by COL3
) as bar
于 2009-06-23T13:07:47.720 に答える
5
SELECT TOP n *
FROM tablename
WHERE key NOT IN (
    SELECT TOP x key
    FROM tablename
    ORDER BY key
    DESC
);
于 2009-04-06T04:28:26.350 に答える
4

LIMIT のみが必要な場合、ms sql には同等の TOP キーワードがあるため、それは明らかです。OFFSET で LIMIT が必要な場合は、前述のようないくつかのハックを試すことができますが、それらはすべてオーバーヘッドを追加します。つまり、ある方法で注文してから別の方法で注文するか、高価な NOT IN 操作です。これらすべてのカスケードは必要ないと思います。私の意見では、最もクリーンな解決策は、SQL 側でオフセットなしで TOP を使用し、適切なクライアント メソッド (php の mssql_data_seek など) で必要な開始レコードをシークすることです。これは純粋な SQL ソリューションではありませんが、オーバーヘッドが追加されないため、最良のソリューションだと思います (スキップされたレコードは、シーク時にネットワーク上で転送されません。 )。

于 2009-05-13T10:06:24.557 に答える
0

ORM では非常に単純なので、これを ORM に実装しようと思います。本当に SQL Server にある必要がある場合は、次の linq to sql ステートメントの linq to sql によって生成されたコードを見て、そこから進みます。そのコードを実装した MSFT エンジニアは、長年 SQL チームの一員であり、自分が何をしているかを知っていました。

var result = myDataContext.mytable.Skip(pageIndex * pageSize).Take(pageSize)

于 2011-06-22T17:37:56.973 に答える