How to select the nth row in a SQL database table?
我有兴趣学习一些(理想情况下)与数据库无关的从数据库表中选择第n行的方法。使用以下数据库的本机功能来实现这一点也很有趣:
- SQL服务器
- MySQL
- 《PostgreSQL》
- 数据库
- 甲骨文公司
我目前正在SQL Server 2005中执行以下操作,但我希望看到其他更不可知论的方法:
1 2 3 4 5 6 |
上述SQL的功劳:Firoz Ansari的日志
更新:参见TrolesArvin关于SQL标准的回答。特洛伊,你有我们可以引用的链接吗?
在标准的可选部分中有一些方法可以做到这一点,但是许多数据库支持它们自己的方法。
一个非常好的站点,可以谈论这个和其他事情,它是http://troels.arvin.dk/db/rdbms/select limit。
PostgreSQL和MySQL基本上支持非标准:
。
Oracle、DB2和MSSQL支持标准窗口功能:
1 2 3 4 5 6 7 |
(我刚从上面链接的网站上复制,因为我从未使用过这些数据库)
更新:从PostgreSQL 8.4开始,支持标准的窗口功能,所以希望第二个示例也适用于PostgreSQL。
更新:sqlite在2018-09-15版本3.25.0中添加了窗口功能支持,因此这两个表单也在sqlite中工作。
PostgreSQL中的
此示例选择第21行。
显然,在疯狂的窗口函数之外,SQL标准对限制问题保持沉默,这就是为什么每个人都不同地实现它的原因。
我不确定其余的内容,但我知道sqlite和mysql没有任何"默认"行排序。至少在这两种方言中,以下代码片段从_表中获取第15个条目,并按添加的日期/时间排序:
(当然,您需要添加一个日期时间字段,并将其设置为添加条目的日期/时间…)
SQL 2005及更高版本内置了此功能。使用row_number()函数。它非常适合使用<
语法:
1 2 3 4 5 6 7 8 9 10 11 12 |
我怀疑这是非常低效的,但这是一种非常简单的方法,它可以处理我尝试过的一个小数据集。
1 2 3 4 |
。
这将得到第五个项目,更改第二个顶部编号以获得不同的第n个项目
SQL Server只能(我认为)运行在不支持row_number()的旧版本上。
在SQL Server上验证:
。
这将为您提供第10行EMP表!
1小变化:N-1而不是N。
。
与某些答案所宣称的相反,SQL标准并没有对此主题保持沉默。
从SQL:2003开始,您就可以使用"窗口函数"跳过行并限制结果集。
在SQL:2008中,增加了一种稍微简单的方法,即使用OCx1(4)
就我个人而言,我不认为真正需要添加SQL:2008,所以如果我是ISO,我会将它排除在已经相当大的标准之外。
SQL SERVER
号
从顶部选择第n条记录
1 2 3 4 5 6 |
。
从底部选择第n条记录
1 2 3 4 5 6 |
神谕:
。
当我们以前在MSSQL2000中工作时,我们做了我们称之为"三重翻转"的工作:
编辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 |
。
它不优雅,速度也不快,但很管用。
这是一个快速解决你困惑的方法。
这里,您可以通过填充n=0得到最后一行,第二行最后一行填充n=1,第四行最后一行填充n=3,依此类推。
这是面试中很常见的问题,而且非常简单。
此外,如果您需要数量、ID或一些数字排序顺序,而不是您在MySQL中使用CAST函数。
。
在这里,填写n=4,您将能够从购物车表中获得金额最高的第五个最后记录。您可以调整字段和表名,并提出解决方案。
添加:
1 |
这将把结果限制为从结果n开始的一个结果。
例如,如果要在mssql中每隔10行选择一次,则可以使用;
1 2 3 4 5 6 |
。
带上mod,把数字10改成你想要的任何数字。
这是我最近为Oracle编写的存储过程的通用版本,它允许动态分页/排序-hth
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | -- 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); |
号
但是,真的,这不是所有这些仅仅是好的数据库设计的会客室技巧吗?有几次我需要这样的功能,一个简单的一次性查询就可以快速生成报告。对于任何真正的工作,使用这样的技巧都会招来麻烦。如果需要选择一个特定的行,那么只需要有一个具有连续值的列,并用它来完成。
限制n,1在MS SQL Server中不起作用。我认为这是唯一一个不支持这种语法的主要数据库。公平地说,它不是SQL标准的一部分,尽管它得到了广泛的支持,应该是这样的。除了SQL Server限制,其他方面都很好。对于SQL Server,我还没有找到一个优雅的解决方案。
在Oracle 12c中,您可以将
例如,要从顶部获取第三条记录:
号
对于SQL Server,按行号排序的一般方法如下:
号
例如:
1 2 3 4 5 |
号
这将返回第20行的信息。之后一定要输入行数0。
在Sybase SQL Anywhere中:
别忘了点菜,要不然就没意义了。
号
T-SQL-从表中选择第n个记录编号
1 2 3 4 5 |
号
例如,要从表Employee中选择第5条记录,您的查询应该是
1 2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
我写了这个查询来查找第n行。这个查询的例子是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
。
对于SQL Server,下面将返回给定表的第一行。
1 2 3 4 |
号
您可以通过如下方式循环遍历这些值:
1 2 3 4 5 6 7 8 9 |
号
没有花哨,没有特殊功能,以防你像我一样使用Cach_…
号
假设您有一个ID列或一个日期戳列,您可以信任它。
这就是我在DB2SQL中实现的方法,我相信RRN(相对记录号)是由O/S存储在表中的;
1 2 3 4 5 |
号
1 2 3 |
号
首先按升序排序选择前100行,然后按降序排序选择最后一行,限制为1。但是,这是一个非常昂贵的语句,因为它两次访问数据。
在我看来,为了提高效率,您需要1)生成一个小于数据库记录数0到1之间的随机数,2)能够选择该位置的行。不幸的是,不同的数据库具有不同的随机数生成器和在结果集中的某个位置选择行的不同方法-通常您指定要跳过的行数和所需的行数,但对于不同的数据库则不同。以下是在sqlite中对我有用的东西:
号
它确实依赖于能够在limit子句中使用子查询(在sqlite中是limit
令人难以置信的是,你能找到一个执行这个任务的SQL引擎…
1 2 3 4 5 6 7 8 9 10 11 |
号