ChatGPT解决这个技术问题 Extra ChatGPT

相当于 SQL Server 的 LIMIT 和 OFFSET?

在 PostgreSQL 中有 LimitOffset 关键字,它们可以很容易地对结果集进行分页。

SQL Server 的等效语法是什么?

对于 sql server 2012,此功能很容易实现。请参阅my answer
感谢您提出这个问题,我们被迫从 MySQL 过渡到 MsSQL :(
ORDER CLAUSE 中的 OFFSET / FETCH 是 SQL ISO 标准。 LIMIT 和 TOP 是供应商解决方案,不能在不同的 RDBMS 之间移植
需要注意的一点是,在使用 Offset Fetch 时,“Order By”子句是强制性的

I
Ian Kemp

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


使用它时是否有 SQL_CALC_FOUND_ROWS 的等价物?
@Petah @@Rowcount 会给你我认为的
GOTCHA:你不能在 CTE 中使用它。它必须在主查询中使用。我想限制返回的行数(分页),然后对返回的 10 行左右执行昂贵的计算,而不是确定行,执行昂贵的计算,然后跳过/获取我需要的内容。 @Aaronaught 的答案适用于那些需要在 CTE 中限制行的人。
@SarojShrestha:这不是 Offset and Fetch 问题。你现在应该重新审视你的桌子的架构。考虑表的分区,您的数据行及其不同的列类型和总表大小,如果不需要定期考虑归档一些行,请检查您的服务器规格。
非常感谢@SomnathMuluk
E
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 开始的索引,而不是正常的从 0 开始的索引。


现在老了。 Sql Server 2012 及更高版本支持 OFFSET/FETCH
@JoelCoehoorn 不老。我刚刚被分配到使用 SLQ Server 2008 的项目,过去只使用过 mysql...
这很好,但需要稍微调整一下WHERE RowNum >= (@Offset + 1)
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。
@Aaronaught 如果我的 Table 有 20 万条记录,它将首先获取所有记录,然后应用限制?这个查询有效吗?
A
Asken
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() 的时候。


我已经使用这个查询有一段时间了,它工作得很好,所以谢谢你。我只是想知道'xx'代表什么?
子查询需要一个名称。因为我没有使用它,所以把 xx 放在那里
xx 只是一个表别名。如果您说AS xx,可能会更清楚一点
任何人都知道如何在这个查询上做左连接?
T
Tom H

您可以在公用表表达式中使用 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

想知道 CTE 内部的 SELECT 是否会首先加载整个表,然后外部 WHERE 是否会过滤掉不需要的记录?还是 SQL 会对其进行优化并避免加载整个 My_Table 的内容?我在问,因为如果它没有并且表有很多记录,它可能效率低下。
通常情况下,SQL Server 会尽可能地围绕 CTE 进行优化。因为这是在做一个 BETWEEN 我不知道它是否会。我在我的手机上,所以我现在不能测试它,但它应该很容易测试。只要确保您使用足够大的数据集,SQL 无论如何都不会加载整个表,并尝试使用从第一行之后某处开始的 BETWEEN。
H
Humayoun_Kabir

特别是对于 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 和 FETCH”,但使用此“ORDER BY”是强制性的

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

希望这对您有所帮助。


s
sebasdev

对我来说,同时使用 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

注意:将 SELECT ROW_NUMBER 与 DISTINCT 一起使用对我不起作用。


我得到“不能在同一查询或子查询中使用 TOP 作为 OFFSET。”
你是对的@MichaelRushton,不能在同一个查询或同一个子查询中使用,那么你必须使用一个子查询来分隔它。因此,如果您有类似 SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows 的 SQL,则必须像 SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1 一样转换它。我将编辑我的答案。谢谢,原谅我的英语。
s
shakeel
-- @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

适用于 Microsoft SQL Server 13.x 非常感谢。
T
Tom

在 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

E
Earlz

另一个样本:

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;

我删除了你的反微软仇恨言论。不要在这里讨论圣战;只是以非主观的方式回答和提问。
C
Community

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


S
Szymon

我能做的最接近的是

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


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

n
noureddine ahmer el kaab
@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

ROW_NUMBER() OVER 是一个缓慢的过程来获得结果......
p
przemo_li

由于还没有人提供此代码:

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 是否明确存在


M
Mike97

详细说明 Somnath-Muluk 的答案只需使用:

SELECT *
FROM table_name_here
ORDER BY (SELECT NULL AS NOORDER)
OFFSET 9 ROWS 
FETCH NEXT 25 ROWS ONLY 

没有添加任何额外的列。在 SQL Server 2019 中进行了测试,但我想也可以在旧版本中使用。


S
SQLMenace

在 SQL 服务器中,您可以将 TOP 与 ROW_NUMBER() 一起使用


V
Vanda Ros

因为,我多次测试这个脚本更有用,每页 100 万条记录 100 条记录分页工作更快我的电脑执行这个脚本 0 秒,而与 mysql 相比有自己的限制和偏移大约 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}:跳过记录数


虽然此代码可能会解决问题,但including an explanation如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答以添加解释并说明适用的限制和假设。