2010-02-17 125 views
1

我正在编写一个web应用程序,它应该在搜索查询中显示非常大的结果。 说一些查询将返回10.000项。 我想将这些显示给用户分页;到目前为止没有问题:每个页面将是带有适当的LIMIT语句的查询的结果。 但我想在分页查询的每个页面中显示结果的线索:来自第一个项目的一些数据和来自最后一个的一些数据。 这意味着,例如,与10.000项目的结果和50项的页面大小,如果用户要求的第一页,我将需要:sql查询得到一个不连续的结果子集

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

对于我想避免一个查询磷效率的原因呃排。

[编辑]我也宁愿不下载10.000的结果,如果我只需要50 +五十零分之万* 2 = 400

的问题是:是否有一个查询我可以发出到RDBMS(MySQL的,顺便说一下,但我更喜欢cross-db解决方案),它只会返回我需要的数据?

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

回答

0

更新:我完全误读了最初的问题。您可以在MySQL中使用UNIONLIMIT子句来完成此操作,但它可能是您“每行一个查询”的含义。语法如下:

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

+1

对不起,误解你的问题(早晨咖啡还在酝酿之中)。我会调整我的答案。 – 2010-02-17 11:36:34

+1

好点:这将最大限度地减少对使用的数据库的依赖:只有限制语法将不得不进行调整。 分页逻辑需要非标准功能。每当我偶然发现这一点,我真的很惊讶:这样一个基本的构造怎么能不被标准化呢? – silviot 2010-02-17 13:20:41

+0

这里的问题是查询不能被参数化。如果我想要100页的话呢?或者如果我想要第100页以及上一页和下一页?然后你必须立即创建SQL。 – 2010-02-17 13:25:39

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。
另外请注意,如果你有gazillion行,你的结果集将有数百万。出于实际原因,您需要最大化结果行。

我不知道如何在通用SQL中解决这个问题。 (我打赌:。没办法,即使简单的pageing离不开特定的DB-运营商来解决)

+0

与Hank Gay提供的(简单的)相比,我应该调查此解决方案的效率。谢谢。 – silviot 2010-02-17 13:22:07