Sql查询获取非连续的结果子集

时间:2010-02-17 11:01:33

标签: sql

我正在编写一个应该在搜索查询中显示非常大的结果的Web应用程序。 假设一些查询将返回10.000项。 我想向用户展示那些分页;到目前为止没问题:每个页面都是具有适当LIMIT语句的查询的结果。 但我想在分页查询的每个页面中显示结果的线索:来自第一个项目的一些数据和来自最后一个项目的一些数据。 这意味着,例如,如果用户要求输入我需要的第一页,则结果为10.000个项目,页面大小为50个项目:

  • 前50个项目(用户请求的页面)
  • 第51和100项(第二页的第一页和最后一页)
  • 项目101和151

出于效率原因,我想避免每行一个查询。

[edit]如果我只需要50 + 10000/50 * 2 = 400

,我也不想下载10.000个结果

问题是:我是否可以向RDBMS发出一个查询(顺便说一句,mysql,但我更喜欢跨数据库解决方案),它只返回我需要的数据?

我无法使用服务器端游标,因为并非所有dbs都支持它,我希望我的应用程序与数据库无关。

2 个答案:

答案 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的易处理问题,因为分页逻辑需要非标准功能。