如何跳过sql查询中的前n行

Posted

技术标签:

【中文标题】如何跳过sql查询中的前n行【英文标题】:How to skip the first n rows in sql query 【发布时间】:2015-04-27 11:37:37 【问题描述】:

我想触发查询“SELECT * FROM TABLE”,但只能从行N+1 中选择。关于如何做到这一点的任何想法?

【问题讨论】:

您使用的是哪个 rdbms(例如 oracle、mysql 或 sql-server)? 哪个 dbms? “OFFSET n”是 ANSI SQL,但许多 dbms 产品以自己的方式执行此操作,例如。限制,顶部... 另外,如果你想在给定的行号范围内查找行,你可以使用像ROW_NUMBER 这样的函数。但这真的取决于你的 dbms。 检查 ROW_NUMBER (). (a) 在关系数据库(即符合关系模型的数据库)中,行是排序的,任何可能的排序需要通过调用代码通过ORDER BY … 显式声明 (b) 我们没有行号或ROW_NUMBER(),,这实际上是一个记录ID。这些是物理记录(不是行)定位器,RM 需要逻辑键。 (c) 因此,在 RDb 中,您的问题不存在,我们 SELECT … WHERE Key >= "value". 它存在于记录归档系统中,没有 RDb 的完整性、能力或速度。 【参考方案1】:

使用这个:

SELECT *
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY

https://***.com/a/19669165/1883345

【讨论】:

注意:此查询仅适用于 SQL Server 2012 及更高版本 另请注意,'new' 语法奇怪地具有与 row_number 方法(索引顺序子句)上的 @skip 线性相关的性能损失。另一方面,语法具有作为纯附件的巨大好处,因此任何由某物生成的脚本,以 order 子句结尾,都可以附加这个。【参考方案2】:

SQL 服务器:

select * from table
except
select top N * from table

Oracle 到 11.2:

select * from table
minus
select * from table where rownum <= N

with TableWithNum as (
    select t.*, rownum as Num
    from Table t
)
select * from TableWithNum where Num > N

Oracle 12.1 及更高版本(遵循标准 ANSI SQL)

select *
from table
order by some_column 
offset x rows
fetch first y rows only

它们可能或多或少地满足您的需求。

没有直接的方法可以通过 SQL 执行您想要的操作。 但是,在我看来,这不是设计缺陷。

不应该这样使用SQL。

在关系数据库中,一个表代表一个关系,它是一个定义的集合。集合包含无序元素。

另外,不要依赖记录的物理顺序。 RDBMS 不保证行顺序。

如果记录的顺序很重要,您最好在表中添加一个列,例如“Num”,并使用以下查询。这样比较自然。

select * 
from Table 
where Num > N
order by Num

【讨论】:

ANSI SQL: "select * from tablename OFFSET n",在这种情况下也推荐使用 ORDER BY。 (a) 是的,很好的答案。请参阅我对问题的评论。 (b) 在最后一句中,您不必添加 列,只需ORDER BY … 所需的任何列,即可获得所需的结果。 (c) 大写ORDER BY.【参考方案3】:

查询:在sql-server

DECLARE @N INT = 5 --Any random number

SELECT * FROM (
        SELECT ROW_NUMBER() OVER(ORDER BY ID) AS RoNum
              , ID --Add any fields needed here (or replace ID by *)
        FROM TABLE_NAME
) AS tbl 
WHERE @N < RoNum
ORDER BY tbl.ID

这将给出表格的行,其中行号从@N + 1 开始。

【讨论】:

答案中的原则是可以的,但是他犯了一个错误并把他的钥匙和计数器都称为同一件事.....更改为“.... as RoNu”,并且"在哪里@N (当然,您通常会包含更多列而不仅仅是 ID,只需用字段列表补充 ID 或在内部选择中用星号替换) 我会做SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0))。这将完全忽略特定列的任何顺序。【参考方案4】:

为了在 SQL Server 中执行此操作,您必须按列对查询进行排序,以便指定所需的行。

例子:

select * from table order by [some_column] 
offset 10 rows
FETCH NEXT 10 rows only

【讨论】:

【参考方案5】:

你想要类似 LINQ 中的跳过 5 并取 10 吗?

SELECT TOP(10) * FROM MY_TABLE  
WHERE ID not in (SELECT TOP(5) ID From My_TABLE ORDER BY ID)
ORDER BY ID;

这种方法适用于任何 SQL 版本。您需要确定一些顺序(例如按 Id),以便以可预测的方式提供所有行。

【讨论】:

这不是一个好方法!无论如何,这两个部分都没有 order 子句,你会得到一个不可预知的结果:Take 10 random 不包括 5 random.... 问题不在于任何特定的顺序。这是关于跳过表中的第一个 N 记录。顺便说一下,Select 不是随机的,它会首先将顺序中的记录插入到表中。 这肯定是关于一个特定的订单,因为它可能不是你在第一次运行中得到的,在第二次被跳过......没有任何保证你得到它们在任何特定命令。尽管可以实现 SQL,因此按顺序添加的未更改的记录将以相同的顺序返回 - 但您不应该假设...... /跨度> ... 在订单部分,请参见例如dba.stackexchange.com/questions/6051/… 正如其他人所说,您绝对需要在此处包含 ORDER BY。 SELECT 不一定会生成按“首先插入表的位置”排序的记录。【参考方案6】:

我知道现在回答这个问题已经很晚了。但是我有一些与其他解决方案不同的解决方案,我认为它们具有更好的性能,因为在 SQL 查询中不进行比较,只进行排序。当 SKIP 的值足够 LARGE 时,基本可以看到它的性能有相当大的提升。

    最佳性能,但仅适用于 SQL Server 2012 及更高版本。原文来自@Majid Basirati's answer,值得再提一下。

    DECLARE @Skip INT = 2, @Take INT = 2
    
    SELECT * FROM TABLE_NAME
    ORDER BY ID ASC
    OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY
    

    不如第一个,但兼容SQL Server 2005 及更高版本

    DECLARE @Skip INT = 2, @Take INT = 2
    
    SELECT * FROM 
    (
        SELECT TOP (@Take) * FROM 
        (
            SELECT TOP (@Take + @Skip) * FROM TABLE_NAME
            ORDER BY ID ASC
        ) T1
        ORDER BY ID DESC
    ) T2
    ORDER BY ID ASC
    

【讨论】:

实际上,如果偏移量不是非常小(小于大约 30),ROW_NUMBER(...) 方法的性能要比 OFFSET 方法好得多。但是在某些情况下,偏移量具有很大的能力,它是对现有有序选择的纯粹附加。(可能是由我们无法控制的东西动态生成的) 我刚刚对一个包含 10,000,000 条记录的复杂记录集进行了一些测试,这些记录集跨 3 个具有日期排序依赖关系的表连接,确实,当偏移量达到 6,000,000 标记时,ROW_NUMBER 方法更快,但是只是名义上如此 - 大约快 25%。有趣的是,在较低的偏移量下,OFFSET 方法要快得多。我认为这是由于我必须做的数据集连接和排序的复杂性。无论如何,感谢这两种方法。我想从现在开始我会坚持使用 OFFSET() 方法,除非我遇到可衡量的性能问题。【参考方案7】:

这个呢:

SELECT * FROM table LIMIT 50 OFFSET 1

【讨论】:

请注意,这不适用于所有类型的 SQL,因为 LIMITOFFSET 关键字不是 ANSI 标准的一部分(请参阅 this question)。 首先应该是OFFSET关键字,然后是LIMIT关键字:SELECT * FROM table OFFSET 1 LIMIT 50【参考方案8】:

这适用于所有 DBRM/SQL,它是标准 ANSI:

SELECT *
  FROM owner.tablename A
 WHERE condition
  AND  n+1 <= (
         SELECT COUNT(DISTINCT b.column_order)
           FROM owner.tablename B
          WHERE condition
            AND b.column_order>a.column_order
          )
ORDER BY a.column_order DESC

【讨论】:

上面的编码选择语句跳过column_order中值较大的前n行。您可以根据需要更改条件以检索更小。【参考方案9】:

在 Faircom SQL(这是一个伪 MySQL)中,我可以在一个超级简单的 SQL 语句中做到这一点,如下所示:

SELECT SKIP 10 * FROM TABLE ORDER BY Id

显然,您可以将 10 替换为您想要的任何已声明变量。

我无法访问 MS SQL 或其他平台,但我会很惊讶 MS SQL 不支持这样的东西。

【讨论】:

【参考方案10】:

PostgreSQL:OFFSET 无限制

支持这种语法,我认为它是其他 DBMS 中最简洁的,因为它没有引入任何新的关键字:

SELECT * FROM mytable ORDER BY mycol ASC OFFSET 1

这是允许的事实可以从:https://www.postgresql.org/docs/13/sql-select.html 因为LIMITOFFSET 可以独立给出,因为OFFSET 在语法规范中不是LIMIT 的子句:

    [ LIMIT  count | ALL  ]
    [ OFFSET start [ ROW | ROWS ] ]

SQLite:负限制

OFFSET 在该 DBMS 中需要 LIMIT,但虚拟负值意味着没有限制。不如 PostgreSQL 好,但它可以工作:

SELECT * FROM mytable ORDER BY mycol ASC LIMIT -1 OFFSET 1

提问于:SQLite with skip (offset) only (not limit)

记录在:https://sqlite.org/lang_select.html

如果 LIMIT 表达式的计算结果为负值,则返回的行数没有上限。

MySQL:使用巨大的限制数

可怕的方法,文档实际上推荐它:

SELECT * FROM tbl LIMIT 1,18446744073709551615;

提问于:MySQL skip first 10 results

Node.js Sequelize ORM 实现了它

那个ORM allows 例如findAll(offset: 不带 limit:,并针对每个不同的 DBMS 实施上述解决方法。

【讨论】:

【参考方案11】:

试试下面的查询它的工作

SELECT * FROM `my_table` WHERE id != (SELECT id From my_table LIMIT 1)

希望这会有所帮助

【讨论】:

【参考方案12】:

您也可以像这样使用 OFFSET 从查询结果中删除第一条记录-

示例 - 从员工表中查找第二个最高薪水

select distinct salary from employee order by salary desc limit 1 OFFSET 1

【讨论】:

【参考方案13】:

对于 SQL Server 2012 及更高版本,最好的方法是 @MajidBasirati 的回答。

我也喜欢@CarlosToledo 的回答,它不限于任何 SQL Server 版本,但它缺少 Order By Clauses。没有它们,它可能会返回错误的结果。

对于 SQL Server 2008 及更高版本,我将使用公用表表达式以获得更好的性能。

-- This example omits first 10 records and select next 5 records
;WITH MyCTE(Id) as
(
    SELECT TOP (10) Id 
    FROM MY_TABLE
    ORDER BY Id
)
SELECT TOP (5) * 
FROM MY_TABLE
    INNER JOIN MyCTE ON (MyCTE.Id <> MY_TABLE.Id) 
ORDER BY Id

【讨论】:

以上是关于如何跳过sql查询中的前n行的主要内容,如果未能解决你的问题,请参考以下文章

Hive / SQL 查询每个键的前 n 个值

求一SQL语句:如何查询最大的前3个值

SQL如何查询表中某一列中的数据的前几位

sql语句中如何 查询结果显示中间几行

SQL如何显示查询结果的前100条?

从 SQL Server 中 4 列的表中获取每组的前 N ​​行