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

时间:2020-03-05 18:40:49  来源:igfitidea点击:

我对学习从数据库表中选择第n行的一些(理想的)数据库不可知方式感兴趣。看看如何使用以下数据库的本机功能来实现此目的也将很有趣:

  • SQL服务器
  • 的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

更新:有关SQL标准,请参见Troels Arvin的答案。 Troels,我们有没有我们可以引用的链接?

解决方案

回答

添加:

LIMIT n,1

这会将结果限制为从结果n开始的一个结果。

回答

LIMIT n,1在MS SQL Server中不起作用。我认为这只是唯一不支持该语法的主要数据库。公平地说,它不是SQL标准的一部分,尽管它得到了应有的广泛支持。除了SQL Server之外,LIMIT在所有情况下都非常有效。对于SQL Server,我一直无法找到一个优雅的解决方案。

回答

这是我最近为Oracle写的sproc的通用版本,它允许动态分页/排序HTH

-- p_LowerBound = first row # in the returned set; if second page of 10 rows,
--                this would be 11 (-1 for unbounded/not set)
-- p_UpperBound = last row # in the returned set; if second page of 10 rows,
--                this would be 20 (-1 for unbounded/not set)

OPEN o_Cursor FOR
SELECT * FROM (
SELECT
    Column1,
    Column2
    rownum AS rn
FROM
(
    SELECT
        tbl.Column1,
        tbl.column2
    FROM MyTable tbl
    WHERE
        tbl.Column1 = p_PKParam OR
        tbl.Column1 = -1
    ORDER BY
        DECODE(p_sortOrder, 'A', DECODE(p_sortColumn, 1, Column1, 'X'),'X'),
        DECODE(p_sortOrder, 'D', DECODE(p_sortColumn, 1, Column1, 'X'),'X') DESC,
        DECODE(p_sortOrder, 'A', DECODE(p_sortColumn, 2, Column2, sysdate),sysdate),
        DECODE(p_sortOrder, 'D', DECODE(p_sortColumn, 2, Column2, sysdate),sysdate) DESC
))
WHERE
    (rn >= p_lowerBound OR p_lowerBound = -1) AND
    (rn <= p_upperBound OR p_upperBound = -1);

回答

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

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

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

回答

我怀疑这是非常低效的,但却是一种非常简单的方法,该方法适用于我尝试过的小型数据集。

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 Server(我认为),但应在不支持ROW_NUMBER()的旧版本上运行。

回答

PostgreSQL中的LIMIT / OFFSET语法为:

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

本示例选择第21行。 " OFFSET 20"告诉Postgres跳过前20条记录。如果我们不指定ORDER BY子句,则无法保证我们将获得哪条记录,这很少有用。

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

回答

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

已编辑

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

SELECT @Count = COUNT(<column>) FROM <TABLE>
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 <TABLE> ORDER BY <column> ASC
    ) AS t1 ORDER BY <column> DESC
) AS t2 ORDER BY <column> ASC'

PRINT @sql
EXECUTE sp_executesql @sql

它不是很优雅,也不是很快,但它确实有效。

回答

甲骨文:

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

回答

但是,真的,所有这些难道不是真的只是为了良好的数据库设计而设计的绝招吗?几次我需要这样的功能,这是一个简单的一次性查询即可快速生成报告。对于任何实际工作,使用这样的技巧都会带来麻烦。如果需要选择特定的行,则只需具有一列具有顺序值的列即可。

回答

在Sybase SQL Anywhere中:

SELECT TOP 1 START AT n * from table ORDER BY whatever

不要忘记ORDER BY或者它毫无意义。

回答

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

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。

回答

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

select *
from thetable
limit n-1, 1

回答

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

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

在SQL:2008中,使用
偏移跳过行
仅获取前n行`

就我个人而言,我不认为确实需要添加SQL:2008,因此,如果我是ISO,我将使它脱离本来就相当大的标准。

回答

令人难以置信的是,我们会发现执行此操作的SQL引擎...

WITH sentence AS
(SELECT 
    stuff,
    row = ROW_NUMBER() OVER (ORDER BY Id)
FROM 
    SentenceType
    )
SELECT
    sen.stuff
FROM sentence sen
WHERE sen.row = (ABS(CHECKSUM(NEWID())) % 100) + 1

回答

SELECT * FROM emp a
WHERE  n = (SELECT COUNT( _rowid)
              FROM emp b
             WHERE a. _rowid >= b. _rowid);

回答

对于SQL Server,按行号排序的通用方法如下:
SET ROWCOUNT @row-@ row =我们要处理的行号。

例如:

将rowcount设置为20-将行设置为第20行

从dbo.sandwich中选择肉类,奶酪-从第20行的表中选择列

set rowcount 0-将行计数设置回所有行

这将返回第20行的信息。请确保之后再放入行计数0。

我知道noobish,但是我是SQL noob,已经用过了,所以我该怎么说?

回答

SQL 2005及更高版本具有此内置功能。使用ROW_NUMBER()函数。对于具有<<上一页和下一页>>样式浏览的网页而言,它非常有用:

句法:

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

回答

T-SQL从表中选择第N个RecordNumber

select * from
 (select row_number() over (order by Rand() desc) as Rno,* from TableName) T where T.Rno = RecordNumber

Where  RecordNumber --> Record Number to Select
       TableName --> To be Replaced with your Table Name

例如要从表Employee中选择第5条记录,查询应为

select * from
 (select row_number() over (order by Rand() desc) as Rno,* from Employee) T where T.Rno = 5