LINQの.Skip(1000).Take(100)を純粋なSQLで書き込むにはどうすればよいですか?


93

.Skip()LINQ のメソッドに相当するSQLは何ですか?

例:特定のデータベーステーブルから行1000〜1100を選択します。

これはSQLだけで可能ですか?または、テーブル全体を選択してからメモリ内の行を見つける必要がありますか?テーブルは非常に大きくなる可能性があるため、できればこれを避けたいと思います。

回答:


78

SQL Server 2005以降では、ROW_NUMBER関数を使用できます。例えば。

USE AdventureWorks;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
    FROM Sales.SalesOrderHeader 
) 
SELECT * 
FROM OrderedOrders 
WHERE RowNumber BETWEEN 51 AND 60; --BETWEEN is inclusive

詳細については、私の回答のリンクを参照してください。stackoverflow.com/questions/1744802/...
マイク・アトラス

51と60の間-それは包括的です。
Drew Miller

1
しかし、これは最初にすべてを選択し、次にその選択から10個だけを右に選びますか?または、最初のクエリ/ビューにはすでに10個しかありませんか?
Tadej 2018年

138

SQL Server 2012以降では、次の構文が追加されています。

SELECT *
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY

11
OFFSETコマンドを使用するには、ORDER BY ___を使用する必要があることに注意してください。
James Haug

また、「新しい」構文には、奇妙なことに@skipと線形のパフォーマンスペナルティがあることに注意してください。row_numberアプローチにはこれがありません(インデックス付きの順序でのみテストされます)。ただし、lo @Skipが約20未満の場合、新しい構文はrow_numberアプローチよりも高速です。
Eske Rahn

22

LINQ to SQLは、ROW_NUMBERウィンドウ関数を使用してこれを行います。

  SELECT a,b,c FROM 
   (SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number
    FROM Table) t0
   WHERE to.row_number BETWEEN 1000 and 1100;

これは機能します、ORDER BYからrow_numberを製造する必要があるため、クエリがサーバー側でソートされ、パフォーマンスの問題が発生する可能性があります。インデックスがORDER BY要件を満たすことができる場合でも、クエリは結果を返す前に1000行をカウントする必要があります。多くの場合、開発者はこれを忘れて、5 milの行テーブルにページ分割コントロールをスローし、最初のページが最後のページよりもはるかに速く返される理由を不思議に思っています...

それでも、ROW_NUMBER()を使用することは、ソートを回避することを確実にすれば、おそらく使いやすさと良好なパフォーマンスとの間の最良のバランスです(ORDER BY条件はインデックスで満たすことができます)。


1
追加のパフォーマンス情報をありがとう、注意してテストする必要があります。
レイ

テストした結果、私の50万行のテーブルでは、その最後のページは最初のページの約7倍遅くなっています。理想的ではありませんが、私には受け入れられます。
レイ

6

これを試してください:

select * from [Table-Name] order by [Column-Name] 
offset [Skip-Count] rows
FETCH NEXT [Take-Count] rows only

例:

select * from Personals order by Id
offset 10 rows            --------->Skip 10
FETCH NEXT 15 rows only   --------->Take 15

4

これを行う:

LINQ to SQLデータコンテキストで.Skip(1000).Take(100)を実行し、SQL出力を確認します。それはあなたが説明していることをするSQL文を生成します。

それはエレガントではありませんが、仕事を成し遂げます。


2
求められていたものではありません。
RayLoveless 2016

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.