SQL Server的LIMIT和OFFSET的等价物?

时间:2010-01-25 20:33:27

标签: sql sql-server limit offset

在PostgreSQL中,有LimitOffset个关键字,可以非常轻松地对结果集进行分页。

Sql Server的等效语法是什么?

16 个答案:

答案 0 :(得分:199)

此功能现在在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

答案 1 :(得分:131)

相当于LIMITSET 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参数应该为此使用基于索引的索引而不是正常的从零开始索引。

答案 2 :(得分: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}

备注: 此解决方案仅适用于SQL Server 2005或更高版本,因为这是在ROW_NUMBER()实施的时候。

答案 3 :(得分:11)

您可以在公用表表达式中使用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 :(得分:3)

对我来说,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对我不起作用。

答案 5 :(得分: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;

答案 6 :(得分:2)

有人here有人在sql 2011中讲述了这个功能,很遗憾他们选择了一个不同的关键字“OFFSET / FETCH”,但它不是标准然后确定。

答案 7 :(得分: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

答案 8 :(得分: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

答案 9 :(得分:2)

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

答案 10 :(得分:1)

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

答案 11 :(得分: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

答案 12 :(得分: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是明确的,如果那是需要的话

答案 13 :(得分:0)

在SQL Server中,您将使用TOP和ROW_NUMBER()

答案 14 :(得分:0)

特别是对于SQL-SERVER,您可以通过许多不同的方式来实现。对于给定的真实示例,我们在此处采用了Customer表。

示例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

希望这对您有所帮助。

答案 15 :(得分:-1)

自此,我测试了该脚本更多次,使每页100万条记录更有用。100条具有分页功能的记录更快,我的PC执行此脚本0秒,而与mysql比较则有自己的限制,并且偏移了4.5秒才能得到结果。

有些人可能会错过了解Row_Number()始终按特定字段排序的知识。如果只需要按顺序定义行,则应使用:

ROW_NUMBER()个(ORDER BY(选择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}:跳过记录的数量