1

ms sqlサーバーで結果をページングしようとしていますが、正しい結果を得るのに問題があります。私は mysql:s LIMIT と同じ結果を達成したいと思っており、このモデルを使用してそれを実行しようとしています:

SELECT * FROM (
    SELECT TOP x * FROM (
        SELECT TOP y fields
        FROM table
        WHERE conditions
        ORDER BY table.field  ASC) as foo
    ORDER by field DESC) as bar
ORDER by field ASC

から: http://josephlindsay.com/archives/2005/05/27/paging-results-in-ms-sql-server/

上位 30 行をリストする元のクエリは次のとおりです。

SELECT TOP 30 pt.[BSNR], t.ID, pt.RESDATUMTID, pt.LAND1, pt.HPL1, pt.ANKDATUMTID, pt.LAND2, pt.HPL2
  FROM [statistik2].[dbo].[ttrip] AS t
  JOIN [statistik2].[dbo].[tparttrip] AS pt 
  ON t.ID = pt.TRIP_ID
  WHERE t.DBKRDAT > '2012-06-27'
  ORDER BY pt.BSNR DESC, t.ID, pt.RESDATUMTID

そして私の試みは:

SELECT * FROM (
    SELECT TOP 10 * FROM (
        SELECT TOP 30 pt.ID AS PTID, pt.[BSNR], t.ID, pt.RESDATUMTID, pt.LAND1, pt.HPL1, pt.ANKDATUMTID, pt.LAND2, pt.HPL2
        FROM [statistik2].[dbo].[ttrip] AS t
        JOIN [statistik2].[dbo].[tparttrip] AS pt
        ON t.ID = pt.TRIP_ID
        WHERE t.DBKRDAT > '2012-06-27'
        ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
    ) as pttt
    ORDER BY pttt.PTID DESC) AS ptttt
ORDER BY ptttt.PTID 

クエリからの出力: http://speedy.sh/5NQeq/sqloutput.txt

誰かが私が間違っていることを説明できますか?

4

2 に答える 2

2

ROW_NUMBER() を使用して実行中のカウントを取得できます-これにより、ページングがはるかに簡単になります...例

(注: これは SQL 2005 以降の場合です - SQL 2000 は row_number() 関数をサポートしていません)

「名前」列が 1 つあるテーブルを想定すると、次のようになります。

SELECT * FROM 
(
    SELECT ROW_NUMBER() OVER (ORDER BY Name) as RunningVal, * FROM Names
) as Running 
WHERE RunningVal BETWEEN 5 AND 10

正直なところ、トリプルソート全体は少し古い学校です:P

あなたの場合、それは次のようになります:

SELECT * FROM (
    SELECT TOP 30 
        ROW_NUMBER() OVER (ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID) as RunningVal, 
        pt.ID AS PTID, 
        pt.[BSNR], 
        t.ID, 
        pt.RESDATUMTID, 
        pt.LAND1, 
        pt.HPL1, 
        pt.ANKDATUMTID, 
        pt.LAND2, 
        pt.HPL2 
    FROM [statistik2].[dbo].[ttrip] AS t 
    JOIN [statistik2].[dbo].[tparttrip] AS pt 
    ON t.ID = pt.TRIP_ID 
    WHERE t.DBKRDAT > '2012-06-27' 
    ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
    ) as Running 
WHERE RunningVal BETWEEN 1 AND 10

実際、内側の TOP を削除して、次のように使用することもできます。

SELECT * FROM (
    SELECT     
        ROW_NUMBER() OVER (ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID) as RunningVal, 
        pt.ID AS PTID, 
        pt.[BSNR], 
        t.ID, 
        pt.RESDATUMTID, 
        pt.LAND1, 
        pt.HPL1, 
        pt.ANKDATUMTID, 
        pt.LAND2, 
        pt.HPL2 
    FROM [statistik2].[dbo].[ttrip] AS t 
    JOIN [statistik2].[dbo].[tparttrip] AS pt 
    ON t.ID = pt.TRIP_ID 
    WHERE t.DBKRDAT > '2012-06-27' 
    ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
    ) as Running 
WHERE RunningVal BETWEEN @x AND @y

@x は下限、@y は上限です (BETWEEN は包括的で、ROW_NUMBER() は 1 から始まるため、x = 1 および y = 10 はレコード 1 ~ 10 を返します)。

編集:範囲外の LIMIT で OFFSET を指定すると、MySql で何が起こるかわかりません (そして、公式ドキュメントでは、私が見る限り、これについて言及していないようです)。 x = 100 および @y = 110 で、テーブルに 50 レコードしかない場合、結果は得られません

Edit2:いじりたい場合は、SQL フィドル リンクを追加しました!

http://sqlfiddle.com/#!3/57808/3

于 2012-06-29T11:58:47.060 に答える
1

サンプル クエリに注意してください。

最も内側のサブクエリは、結果を で並べ替えfield ASCます。それがすべてのページの主な順序です。最も内側のサブクエリは、yその順序で一番上の行を取ります。

中間層のサブクエリは順序を逆にして、前の結果からx上位の行を取得するため、データセット全体の上位の行の下位の行を効果的に取得します。xy

メインクエリは、行の主な順序を再確立するだけです。

同じことをする必要があります。最も内側のクエリは、次のように行を並べ替えます。

ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID

それがメインの行の順序である場合は、中間層のサブクエリで逆バージョンを使用する必要があります。つまり、次のようになります。

ORDER BY pt.BSNR ASC, t.ID ASC, pt.RESDATUMTID DESC

メイン クエリで行をどのように並べるかはそれほど重要ではないかもしれませんが、サンプルに従い、順序をもう一度逆にして、最も内側のクエリと一致させます。

于 2012-06-29T11:58:08.993 に答える