我感兴趣的是从数据库表中选择第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,你有我们可以引用的链接吗?


当前回答

ADD:

LIMIT n,1

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

其他回答

下面是我最近为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);

LIMIT n,1不能在MS SQL Server中工作。我认为它是唯一一个不支持这种语法的主流数据库。公平地说,它不是SQL标准的一部分,尽管它得到了如此广泛的支持,它应该是SQL标准的一部分。在一切除了SQL服务器限制工作得很好。对于SQL server,我还没有找到一个优雅的解决方案。

这就是我在DB2 SQL中如何做的,我相信RRN(相对记录号)由O/S存储在表中;

SELECT * FROM (                        
               SELECT RRN(FOO) AS RRN, FOO.*
               FROM FOO                         
               ORDER BY RRN(FOO)) BAR             
WHERE BAR.RRN = recordnumber

但说真的,所有这些不都是好的数据库设计的小把戏吗?有几次我需要这样的功能,它是为了一个简单的一次性查询,以快速生成报告。对于任何实际工作,使用这样的技巧都是在招惹麻烦。如果需要选择一个特定的行,那么只要有一个具有连续值的列就可以了。

在Oracle 12c中,你可以使用OFFSET..FETCH..带有ORDER BY的ROWS选项

例如,要从顶部获取第3条记录:

SELECT * 
FROM   sometable
ORDER BY column_name
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY;