我正在编写一个应该在搜索查询中显示非常大的结果的Web应用程序。 假设一些查询将返回10.000项。 我想向用户展示那些分页;到目前为止没问题:每个页面都是具有适当LIMIT语句的查询的结果。 但我想在分页查询的每个页面中显示结果的线索:来自第一个项目的一些数据和来自最后一个项目的一些数据。 这意味着,例如,如果用户要求输入我需要的第一页,则结果为10.000个项目,页面大小为50个项目:
等
出于效率原因,我想避免每行一个查询。
[edit]如果我只需要50 + 10000/50 * 2 = 400
,我也不想下载10.000个结果问题是:我是否可以向RDBMS发出一个查询(顺便说一句,mysql,但我更喜欢跨数据库解决方案),它只返回我需要的数据?
我无法使用服务器端游标,因为并非所有dbs都支持它,我希望我的应用程序与数据库无关。
答案 0 :(得分:2)
只是为了好玩,这是它的MSSQL版本。
declare @pageSize as int; set @pageSize = 10;
declare @pageIndex as int; set @pageIndex = 0; /* first page */
WITH x AS
(
select
ROW_NUMBER() OVER (ORDER BY (created) ASC) AS RowNumber,
*
from table
)
SELECT * FROM x
WHERE
((RowNumber <= (@pageIndex+1)*@pageSize) AND (RowNumber >= @pageIndex*@PageSize+1))
OR
RowNumber % @pageSize = 1
OR
RowNumber % @pageSize = @pageSize-1
请注意,over子句中提供了ORDER BY 另请注意,如果您有大量行,您的结果集将有数百万。出于实际原因,您需要最大化结果行。
我不知道如何在通用SQL中解决这个问题。 (我敢打赌:没办法。如果没有特定于DB的操作员,即使是简单的页面也无法解决。)
答案 1 :(得分:0)
更新:我完全误读了最初的问题。您可以使用UNION
和MySQL中的LIMIT
子句来执行此操作,尽管它可能是“每行一个查询”的含义。语法如下:
select FOO from BAZ limit 50
union
select FOO from BAZ limit 50, 1
union
select FOO from BAZ limit 99, 1
union
select FOO from BAZ limit 100, 1
union
select FOO from BAZ limit 149, 1
依此类推。由于您使用的是UNION
,因此您只需要往返数据库一次。不过,我不确定MySQL如何处理各种SELECT
语句。它应能够识别它们本质上是相同的查询并使用缓存的查询计划,但我不能使用MySQL足以知道它是否是对其优化器的合理期望。
显然,要以一般方式构建此查询,您首先需要运行count
查询,以便计算您的偏移量。
这绝对不是标准SQL的易处理问题,因为分页逻辑需要非标准功能。