web-dev-qa-db-ja.com

SQL ServerのLIMITおよびOFFSETと同等ですか?

PostgreSQLには、LimitおよびOffsetキーワードがあり、結果セットのページ分割が非常に簡単になります。

Sql Serverの同等の構文は何ですか?

154
Earlz

LIMITに相当するものはSET ROWCOUNTですが、一般的なページネーションが必要な場合は、次のようなクエリを作成することをお勧めします。

;WITH Results_CTE AS
(
    SELECT
        Col1, Col2, ...,
        ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
    FROM Table
    WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit

ここでの利点は、ページングオプションを変更する(またはユーザーが変更できるようにする)場合にオフセットと制限をパラメーター化することです。

注:@Offsetパラメーターは、通常のゼロベースのインデックス付けではなく、1ベースのインデックス付けを使用する必要があります。

132
Aaronaught

この機能は、SQL Server 2012で簡単になりました。これは、SQL Server 2012以降で機能しています。

SQL Serverで11〜20行を選択するためのオフセット制限:

SELECT email FROM emailTable 
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
  • OFFSET:スキップされた行の数
  • NEXT:次の行の必要数

参照: https://docs.Microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017

202
Somnath Muluk
select top {LIMIT HERE} * from (
      select *, ROW_NUMBER() over (order by {ORDER FIELD}) as r_n_n 
      from {YOUR TABLES} where {OTHER OPTIONAL FILTERS}
) xx where r_n_n >={OFFSET HERE}

注意:このソリューションは、ROW_NUMBER()が実装されていたため、SQL Server 2005以降でのみ機能します。

23
jorgeu

これを実現するには、共通テーブル式でROW_NUMBERを使用できます。

;WITH My_CTE AS
(
     SELECT
          col1,
          col2,
          ROW_NUMBER() OVER(ORDER BY col1) AS row_number
     FROM
          My_Table
     WHERE
          <<<whatever>>>
)
SELECT
     col1,
     col2
FROM
     My_CTE
WHERE
     row_number BETWEEN @start_row AND @end_row
11
Tom H

私にとって、OFFSETとFETCHの併用は遅いため、TOPとOFFSETの組み合わせを次のように使用しました(高速でした)。

SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

注: TOPとOFFSETを同じクエリで一緒に使用する場合:

SELECT TOP 20 columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS

その後、エラーが発生するため、TOPとOFFSETを一緒に使用するには、サブクエリでエラーを分離する必要があります。

SELECT DISTINCTを使用する必要がある場合、クエリは次のようになります。

SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

注: DISTINCTでのSELECT ROW_NUMBERの使用は機能しませんでした。

3
sebasdev

一番近いのは

select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber  and ct <= toNumber

select * from [db].[dbo].[table] LIMIT 0, 10に似ていると思います

2
user2991730

Aaronaughtのソリューションにわずかなバリエーションを追加して、通常、ページ番号(@PageNum)とページサイズ(@PageSize)をパラメーター化します。このように、各ページクリックイベントは、要求されたページ番号と設定可能なページサイズを送信するだけです。

begin
    with My_CTE  as
    (
         SELECT col1,
              ROW_NUMBER() OVER(ORDER BY col1) AS row_number
     FROM
          My_Table
     WHERE
          <<<whatever>>>
    )
    select * from My_CTE
            WHERE RowNum BETWEEN (@PageNum - 1) * (@PageSize + 1) 
                              AND @PageNum * @PageSize

end
2
Tom

here SQL 2011でこの機能について誰かが言っていますが、悲しいことに彼らは少し異なるキーワード "OFFSET/FETCH"を選択しますが、標準ではありません。

-- @RowsPerPage  can be a fixed number and @PageNumber number can be passed 
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 2

SELECT *

FROM MemberEmployeeData

ORDER BY EmployeeNumber

OFFSET @PageNumber*@RowsPerPage ROWS

FETCH NEXT 10 ROWS ONLY
2
shakeel

別のサンプル:

declare @limit int 
declare @offset int 
set @offset = 2;
set @limit = 20;
declare @count int
declare @idxini int 
declare @idxfim int 
select @idxfim = @offset * @limit
select @idxini = @idxfim - (@limit-1);
WITH paging AS
    (
        SELECT 
             ROW_NUMBER() OVER (order by object_id) AS rowid, *
        FROM 
            sys.objects 
    )
select *
    from 
        (select COUNT(1) as rowqtd from paging) qtd, 
            paging 
    where 
        rowid between @idxini and @idxfim
    order by 
        rowid;
2
sillyim

まだ誰もこのコードを提供していないため:

SELECT TOP @limit f1, f2, f3...
FROM t1
WHERE c1 = v1, c2 > v2...
AND
    t1.id NOT IN
        (SELECT TOP @offset id
         FROM t1
         WHERE c1 = v1, c2 > v2...
         ORDER BY o1, o2...)
ORDER BY o1, o2...

重要なポイント:

  • ORDER BYは同一でなければなりません
  • @limitは、取得する結果の数に置き換えることができます。
  • @offsetはスキップする結果の数です
  • 以前のソリューションと比較してパフォーマンスが効率的である可能性があるため、パフォーマンスを比較してください
  • このソリューションはwhere句とorder by句を複製し、それらが同期していない場合、誤った結果を提供します
  • 一方、order byは、必要な場合に明示的に存在します
1
przemo_li
@nombre_row :nombre ligne par page  
@page:numero de la page

//--------------code sql---------------

declare  @page int,@nombre_row int;
    set @page='2';
    set @nombre_row=5;
    SELECT  *
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY etudiant_ID ) AS RowNum, *
      FROM      etudiant

    ) AS RowConstrainedResult
WHERE   RowNum >= ((@page-1)*@nombre_row)+1
    AND RowNum < ((@page)*@nombre_row)+1
ORDER BY RowNum
select top (@TakeCount) * --FETCH NEXT
from(
    Select  ROW_NUMBER() OVER (order by StartDate) AS rowid,*
    From YourTable
)A
where Rowid>@SkipCount --OFFSET
1
Barny

SQLサーバーでは、TOPをROW_NUMBER()と一緒に使用します

0
SQLMenace