当前位置:  开发笔记 > 后端 > 正文

如何在SQL数据库表中选择第n行?

如何解决《如何在SQL数据库表中选择第n行?》经验,为你挑选了11个好方法。

我有兴趣学习一些(理想情况下)数据库无关的方法来从数据库表中选择第n行.看看如何使用以下数据库的本机功能实现这一目标也很有趣:

SQL Server

MySQL的

PostgreSQL的

SQLite的

神谕

我目前正在SQL Server 2005中执行类似下面的操作,但我有兴趣看到其他更不可知的方法:

WITH Ordered AS (
SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS RowNumber, OrderID, OrderDate
FROM Orders)
SELECT *
FROM Ordered
WHERE RowNumber = 1000000

感谢上述SQL:Firoz Ansari的Weblog

更新:请参阅Troels Arvin关于SQL标准的答案.Troels,您有任何我们能引用的链接吗?



1> Henrik Gusta..:

有很多方法可以在标准的可选部分中执行此操作,但许多数据库都支持自己的方法.

讨论这个和其他事情的一个非常好的网站是http://troels.arvin.dk/db/rdbms/#select-limit.

基本上,PostgreSQL和MySQL支持非标准:

SELECT...
LIMIT y OFFSET x 

Oracle,DB2和MSSQL支持标准窗口函数:

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
    columns
  FROM tablename
) AS foo
WHERE rownumber <= n

(我刚从上面链接的网站复制,因为我从未使用过这些数据库)

更新:从PostgreSQL 8.4开始,支持标准的窗口函数,所以期望第二个例子也适用于PostgreSQL.

更新: SQLite在2018-09-15版本的3.25.0中添加了窗口函数支持,因此这两种形式也适用于SQLite.


不应该是`WHERE rownumber = n`才能获得第n行?
MySQL也使用OFFSET和LIMIT语法.Firebird使用FIRST和SKIP关键字,但它们是在SELECT之后放置的.

2> Neall..:

PostgreSQL中的LIMIT/ OFFSET语法是:

SELECT
    *
FROM
    mytable
ORDER BY
    somefield
LIMIT 1 OFFSET 20;

此示例选择第21行.OFFSET 20告诉Postgres跳过前20条记录.如果您没有指定一个ORDER BY条款,则无法保证您将获得哪条记录,这很少有用.

显然,SQL标准对疯狂窗口函数之外的限制问题保持沉默,这就是每个人以不同方式实现它的原因.



3> Ellen Teapot..:

我不确定其余的,但我知道SQLite和MySQL没有任何"默认"行排序.在这两种方言中,至少,以下片段从the_table中获取第15个条目,按添加的日期/时间排序:

SELECT * FROM the_table ORDER BY added DESC LIMIT 1,15

(当然,您需要添加一个DATETIME字段,并将其设置为添加条目的日期/时间......)



4> Ben Breen..:

SQL 2005及更高版本内置了此功能.使用ROW_NUMBER()函数.它非常适合浏览"上一页和下一页"样式的网页:

句法:

SELECT
    *
FROM
    (
        SELECT
            ROW_NUMBER () OVER (ORDER BY MyColumnToOrderBy) AS RowNum,
            *
        FROM
            Table_1
    ) sub
WHERE
    RowNum = 23



5> Tim Saunders..:

我怀疑这是非常低效的,但这是一个非常简单的方法,它适用于我尝试过的小数据集.

select top 1 field
from table
where field in (select top 5 field from table order by field asc)
order by field desc

这将获得第5项,更改第二个顶部数字以获得不同的第n项

仅限SQL服务器(我认为)但应该适用于不支持ROW_NUMBER()的旧版本.



6> Nick Berardi..:

1个小变化:n-1而不是n.

select *
from thetable
limit n-1, 1



7> Rameshwar Pa..:

在SQL Server上验证它:

Select top 10 * From emp 
EXCEPT
Select top 9 * From emp

这将给你第10个emp表的行!



8> Troels Arvin..:

与某些答案所声称的相反,SQL标准并未对此主题保持沉默.

从SQL:2003开始,您就可以使用"窗口函数"来跳过行并限制结果集.

在SQL:2008中,使用了一种稍微简单的方法
OFFSET skip ROWS FETCH FIRST n ROWS ONLY

就个人而言,我不认为SQL:2008的添加是真的需要,所以如果我是ISO,我会把它保留在已经相当大的标准之外.



9> Adam V..:

当我们以前在MSSQL 2000中工作时,我们做了所谓的"三重翻转":

EDITED

DECLARE @InnerPageSize int
DECLARE @OuterPageSize int
DECLARE @Count int

SELECT @Count = COUNT() FROM 
SET @InnerPageSize = @PageNum * @PageSize
SET @OuterPageSize = @Count - ((@PageNum - 1) * @PageSize)

IF (@OuterPageSize < 0)
    SET @OuterPageSize = 0
ELSE IF (@OuterPageSize > @PageSize)
    SET @OuterPageSize = @PageSize

DECLARE @sql NVARCHAR(8000)

SET @sql = 'SELECT * FROM
(
    SELECT TOP ' + CAST(@OuterPageSize AS nvarchar(5)) + ' * FROM
    (
        SELECT TOP ' + CAST(@InnerPageSize AS nvarchar(5)) + ' * FROM 
ORDER BY ASC ) AS t1 ORDER BY DESC ) AS t2 ORDER BY ASC' PRINT @sql EXECUTE sp_executesql @sql

它并不优雅,并不快,但它确实有效.



10> Aditya..:

SQL SERVER


从顶部选择第n条记录

SELECT * FROM (
SELECT 
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID) AS ROW
FROM TABLE 
) AS TMP 
WHERE ROW = n

从底部选择第n条记录

SELECT * FROM (
SELECT 
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID DESC) AS ROW
FROM TABLE 
) AS TMP 
WHERE ROW = n



11> Mark Harriso..:

甲骨文:

select * from (select foo from bar order by foo) where ROWNUM = x

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有