SQL Server에 대한 LIMIT 및 OFFSET에 해당합니까?


172

PostgreSQL에는 결과 세트를 매우 쉽게 페이지 매김 할 수 있는 LimitOffset키워드가 있습니다.

SQL Server에 해당하는 구문은 무엇입니까?


SQL Server 2012의 경우이 기능은 쉽게 구현됩니다. 내 답변
Somnath Muluk

이 질문을 해주셔서 감사합니다. 우리는 MySQL에서
MsSQL

order by 절과 함께 SQL Server에서 offset 및 fetch next 문을 사용할 수 있습니다. 그것을보십시오 youtu.be/EqHkAiiBwPc
Amresh Kumar Singh

답변:


139

의 상응 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 매개 변수는 정상 제로 인덱스보다이 아니라 하나 기반의 인덱싱을 사용해야합니다.


22
옛날이야 SQL 서버 2012 이후 지원은 FETCH / OFFSET
조엘 Coehoorn

31
@JoelCoehoorn 오래되지 않았습니다. 방금 과거에 mysql 만 사용한 SLQ Server 2008을 사용하여 프로젝트에 배정되었습니다.
Cthulhu

이것은 꽤 좋지만 약간 조정되어야합니다WHERE RowNum >= (@Offset + 1)
Eric Herlitz

5
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified. MSSQL2008 R2.
Paul

2
@Aaronaught Table200k 개의 레코드가 있으면 먼저 모든 레코드를 가져온 다음 한도를 적용합니까? 이 쿼리는 효율적입니까?
Jigar

231

이 기능은 이제 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


4
의 당량 거기에 SQL_CALC_FOUND_ROWS이를 사용하는 경우는?
Petah

1
@Petah @@ Rowcount는 내가 생각하는 것을 줄 것입니다
Rob Sedgwick

GOTCHA : CTE 내에서는 이것을 사용할 수 없습니다. 기본 쿼리에서 사용해야합니다. 반환 된 행의 양 (페이지 매김)을 제한 한 다음 행을 결정하고 값 비싼 계산을 수행 한 다음 필요한 것을 건너 뛰지 않고 반환 된 10 개 정도의 행으로 비싼 계산을 수행하려고했습니다. @Aaronaught의 답변은 CTE 내에서 행을 제한 해야하는 사람들에게 효과적입니다.
Derreck Dean

@Somnath Muluk이 오프셋 및 가져 오기는 오프셋이 1000000 인 더 많은 양의 데이터 예제에 많은 시간이 걸립니다. 어떻게 처리 할 수 ​​있습니까?
Saroj Shrestha

1
@SarojShrestha : 이것은 오프셋 및 페치 문제가 아닙니다. 이제 테이블 아키텍처를 다시 방문해야합니다. 테이블, 데이터 행 및 다른 열 유형 및 총 테이블 크기의 분할을 고려하고, 정기적으로 필요하지 않은 경우 일부 행을 아카이브하는 것을 고려하고 서버 사양을 확인하십시오.
Somnath Muluk

23
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 이상에서만 작동 합니다.


나는이 쿼리를 잠시 동안 사용 해 왔으며 훌륭하게 작동하므로 감사합니다. 'xx'가 무엇을 나타내는 지 궁금합니다.
Urbley

하위 쿼리에는 이름이 필요합니다. 내가 그것을 사용하지 않기 때문에 그냥 거기에 xx를 넣어
jorgeu

2
xx는 테이블 별칭 일뿐입니다. 당신이 말하면 조금 더 명확 할 것입니다AS xx
Concrete Gannet

누구나이 쿼리에 왼쪽 조인을 수행하는 방법을 알고 있습니까?
Drenyl

12

공통 테이블 표현식에서 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

4

나를 위해 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를 사용하면 효과가 없었습니다.


1
"TOP은 OFFSET과 동일한 쿼리 또는 하위 쿼리에서 사용할 수 없습니다."
MichaelRushton

당신은 맞습니다 @MichaelRushton, 같은 쿼리 또는 동일한 하위 쿼리에서 사용할 수 없으며 하위 쿼리를 사용하여 분리해야합니다. 따라서 SQL과 같은 것이 있으면 SQL과 같이 SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows변환해야합니다 SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1. 답변을 편집하겠습니다. 고마워 영어 실례합니다
sebasdev

2

다른 샘플 :

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;

15
나는 당신의 안티 혐오 연설을 제거했습니다. 여기에서 거룩한 전쟁에 대해 이야기하지 마십시오. 비 주관적인 방식으로 답변하고 질문하십시오.
Earlz

2

여기에 이 SQL 2011 년 기능, 슬픈 그들은 "FETCH / OFFSET"조금 다른 키워드를 선택는하지만 STANDART 한 다음 확인을하지 대한 사람의 이야기는.


2

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

내가 할 수있는 가장 가까운 것은

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


1
select top (@TakeCount) * --FETCH NEXT
from(
    Select  ROW_NUMBER() OVER (order by StartDate) AS rowid,*
    From YourTable
)A
where Rowid>@SkipCount --OFFSET

1
@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

1

아무도이 코드를 아직 제공하지 않았으므로 :

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 건너 뛸 결과 수
  • 더 효율적일 수 있으므로 이전 솔루션과 성능을 비교하십시오
  • 이 솔루션은 복제 whereorder by절이며 동기화되지 않은 경우 잘못된 결과를 제공합니다
  • 반면 order by에 그것이 필요한 경우 명시 적으로 있습니다

1
-- @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

1

특히 SQL-SERVER의 경우 여러 가지 방법으로이를 달성 할 수 있습니다. 실제 예제에서는 고객 테이블을 사용했습니다.

예 1 : "SET ROWCOUNT"사용

SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName

모든 행을 리턴하려면 ROWCOUNT를 0으로 설정하십시오.

SET ROWCOUNT 0  
SELECT CustomerID, CompanyName from Customers
    ORDER BY CompanyName

예 2 : "ROW_NUMBER 및 OVER"사용

With Cust AS
( SELECT CustomerID, CompanyName,
ROW_NUMBER() OVER (order by CompanyName) as RowNumber 
FROM Customers )
select *
from Cust
Where RowNumber Between 0 and 10

예 3 : "OFFSET and FETCH"를 사용하지만이 "ORDER BY"는 필수

SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY

이것이 도움이되기를 바랍니다.


-1

SQL 서버에서는 TOP을 ROW_NUMBER ()와 함께 사용합니다.


-1

이 스크립트는 페이지 당 100 만 개의 레코드로 100 만 레코드를 더 유용하게 테스트하기 때문에 PC에서이 스크립트를 0 초 더 빠르게 실행하는 반면 mysql과 비교할 때 4.5 초의 오프셋과 4.5 초의 오프셋으로 결과를 얻을 수 있습니다.

Row_Number ()가 항상 특정 필드를 기준으로 정렬한다는 것을 이해하지 못할 수 있습니다. 순서대로 행만 정의 해야하는 경우 다음을 사용해야합니다.

ROW_NUMBER () OVER (ORDER BY (SELECT NULL))

SELECT TOP {LIMIT} * FROM (
      SELECT TOP {LIMIT} + {OFFSET} ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ROW_NO,*
      FROM  {TABLE_NAME}
) XX WHERE ROW_NO > {OFFSET}

설명:

  • {LIMIT} : 각 페이지의 레코드 수
  • {OFFSET} : 건너 뛰기 레코드 수

2
이 코드가 문제를 해결하는 방법과 이유에 대한 설명포함 하여 질문을 해결할 수는 있지만 게시물의 품질을 향상시키는 데 도움이되고 더 많은 투표를 할 수 있습니다. 지금 질문하는 사람 만이 아니라 앞으로 독자들에게 질문에 대답하고 있음을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
브라이언
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.