web-dev-qa-db-ja.com

SQL ServerでOrder Byを使用せずにオフセットとフェッチを使用する方法

SQL Server 2012クエリでOFFSETとFetchを使用したいのですが、order byがないと、order byを使用できません。ソート順が失われるためです。 OFFSETとFetchを、注文番号、行番号なし、クエリのどこで使用するにはどうすればよいですか?私の2つの選択テーブルは同じ構造です。

INSERT INTO @TempTable [some columns]  
select [some columns] from table1 order by col1 
INSERT INTO @TempTable [same columns]
select [some columns] from table2 order by col2
select * from @TempTable OFFSET 20 ROWS FETCH NEXT 50 ROWS ONLY

このクエリのOFFSETキーワードに構文エラーがあります。

一時テーブル変数にID列を追加する

    declare @TempTable table([some columns], rownr int identity(1,1) )

    INSERT INTO @TempTable [some columns]  
    select [some columns] from table1  order by col1 

    INSERT INTO @TempTable [same columns]
    select [some columns] from table2 order by col2

自動インクリメント番号は、一時テーブルに追加された順序で、各行に追加されます。挿入はこの列を満たす必要がないため、挿入はそのままにしておくことができます。 ID列は、次の方法で注文に使用できます。

 select * from @TempTable Order by rownr OFFSET 20 ROWS FETCH NEXT 50 ROWS ONLY
9
Me.Name

ダミーのORDER BY句を提供するさらに簡単な方法があります。

select * from @TempTable ORDER BY(SELECT NULL) OFFSET 20 ROWS FETCH NEXT 50 ROWS ONLY
34
Jörg

OFFSETおよびFETCHを使用したORDER BYの必須構文の使用は避けられません。

ただし、レコード挿入プロセスで作成されたテーブルの自然な順序からページングを実行するために指定する必要があるORDER BY句の関連付けを解除することは可能です。

以下のソリューションを使用すると、基礎となるテーブルに変更を加える必要もありません

Select 0 as TempSort, T.* From MyTable T ORDER BY TempSort OFFSET 2 ROWS FETCH NEXT 3 ROWS
16
pixelda

オフセット/フェッチには、order by句が必要です。注文したくない場合は、CURRENT_TIMESTAMPを使用してこの要件をバイパスできます。確かではありませんが、これはストレージの順序に基づいて行を返すはずです(クラスター化インデックスが多分)

したがって、コードをこれに変更すると問題が解決します-

INSERT INTO @TempTable [some columns]  
select [some columns] from table1 order by col1 
INSERT INTO @TempTable [same columns]
select [some columns] from table2 order by col2
select * from @TempTable **order by current_timestamp** OFFSET 20 ROWS FETCH NEXT 50 ROWS ONLY
0
Diptiman Singh

調査後、コメントによると、明確かつ要約的な回答は次のとおりです。"方法はありません!"

ただし、row_number()を使用してソート順を維持できます。そこで、OFFSETとFETCH句を使用して一時テーブル(ファイナルテーブル)の並べ替え順序を維持した新しいテスト済みクエリを提供しました。

    INSERT INTO @TempTable [some columns]  
    select [some columns],row_number() OVER (order by col1) row from table1 order by col1 

    declare @maxrow int
    select @maxrow=max(rn) from @TempTable

    INSERT INTO @TempTable [same columns]
    select [some columns],((row_number() OVER (order by col2)) + @maxrow) row from table2 order by col2

    select * from @TempTable Order by row  OFFSET 20 ROWS FETCH NEXT 50 ROWS ONLY