[sql] SQL Server의 행 오프셋

주어진 오프셋에서 시작하여 결과를 얻는 방법이 SQL Server에 있습니까? 예를 들어, 다른 유형의 SQL 데이터베이스에서 다음을 수행 할 수 있습니다.

SELECT * FROM MyTable OFFSET 50 LIMIT 25

결과 51-75를 얻을 수 있습니다. 이 구문은 SQL Server에 존재하지 않는 것 같습니다.

신경 쓰지 않는 모든 행을로드하지 않고 어떻게 이것을 할 수 있습니까? 감사!



답변

사용하지 않는 것이 SELECT *좋습니다. 실제로 원하는 열을 모두 지정할 수 있습니다.

SQL Server 2005 이상

SELECT col1, col2
FROM (
    SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum
    FROM MyTable
) AS MyDerivedTable
WHERE MyDerivedTable.RowNum BETWEEN @startRow AND @endRow

SQL Server 2000

SQL Server 2000에서 큰 결과 집합을 통해 효율적으로 페이징

큰 결과 집합을 통한 페이징을위한보다 효율적인 방법


답변

당신은 단순히 이전 페이지에서 볼 수있는 마지막 키 값을 기억하고 사용하여 다음 순서에있는 모든 페이지를 처리 할 경우 TOP (25) ... WHERE Key > @last_key ORDER BY Key또는 – 적절한 인덱스이 효율적으로 탐색했습니다 될 수 있도록 존재하는 경우 실적이 가장 좋은 방법이 될 수 있는 API 커서 그렇지 않은 경우 .

SQL 서버 2005에 대한 인해 임의 페이지에게 최적의 솔루션을 선택하는 – 2008 R2는 아마 ROW_NUMBERBETWEEN

SQL Server 2012+의 경우이 요구에 향상된 ORDER BY 절을 사용할 수 있습니다 .

SELECT  *
FROM     MyTable
ORDER BY OrderingColumn ASC
OFFSET  50 ROWS
FETCH NEXT 25 ROWS ONLY 

하지만 그것은두고 봐야 알 겠죠 수행이 옵션을 얼마나 잘 될 것입니다 .


답변

이것은 한 가지 방법입니다 (SQL2000)

SELECT * FROM
(
    SELECT TOP (@pageSize) * FROM
    (
        SELECT TOP (@pageNumber * @pageSize) *
        FROM tableName
        ORDER BY columnName ASC
    ) AS t1
    ORDER BY columnName DESC
) AS t2
ORDER BY columnName ASC

그리고 이것은 다른 방법입니다 (SQL 2005)

;WITH results AS (
    SELECT
        rowNo = ROW_NUMBER() OVER( ORDER BY columnName ASC )
        , *
    FROM tableName
)
SELECT *
FROM results
WHERE rowNo between (@pageNumber-1)*@pageSize+1 and @pageNumber*@pageSize


답변

ROW_NUMBER()함수를 사용 하여 원하는 것을 얻을 수 있습니다 .

SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t
WHERE RowNr BETWEEN 10 AND 20


답변

OFFSET .. FETCHSQL 서버 2012 년,하지만 당신은 지정해야합니다 ORDER BY열을.

열로 전달할 수있는 명시 적 열이없는 경우 ORDER BY(다른 사람이 제안한대로)이 트릭을 사용할 수 있습니다.

SELECT * FROM MyTable
ORDER BY @@VERSION
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY

… 또는

SELECT * FROM MyTable
ORDER BY (SELECT 0)
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY

사용자가 명시 적으로 주문을 지정하지 않으면 jOOQ 에서 사용됩니다 . 그러면 추가 비용없이 무작위로 주문할 수 있습니다.


답변

데이터 열이 많고 큰 테이블의 경우 다음을 선호합니다.

SELECT
  tablename.col1,
  tablename.col2,
  tablename.col3,
  ...
FROM
(
  (
    SELECT
      col1
    FROM
    (
      SELECT col1, ROW_NUMBER() OVER (ORDER BY col1 ASC) AS RowNum
      FROM tablename
      WHERE ([CONDITION])
    )
    AS T1 WHERE T1.RowNum BETWEEN [OFFSET] AND [OFFSET + LIMIT]
  )
  AS T2 INNER JOIN tablename ON T2.col1=tablename.col1
);

[CONDITION] can contain any WHERE clause for searching.
[OFFSET] specifies the start,
[LIMIT] the maximum results.

ROW_NUMBER 함수는 하나의 열만 살펴보고 일치하는 행만 모든 열과 함께 리턴하므로 BLOB와 같은 큰 데이터가있는 테이블에서 성능이 훨씬 우수합니다.


답변

페이지 매김에 대한 내 선택 참조

SELECT TOP @limit * FROM (
   SELECT ROW_NUMBER() OVER (ORDER BY colunx ASC) offset, * FROM (

     -- YOU SELECT HERE
     SELECT * FROM mytable


   ) myquery
) paginator
WHERE offset > @offset

이것은 페이지 매김을 해결합니다.)