我正在使用SQL Server 2008和以下查询从我们的JSF应用程序实现分页数据检索,在下面的代码中我一次检索25行 默认排序DESC命令中的列。
SELECT * FROM
(
SELECT TOP 25 * FROM
(
SELECT TOP 25 ...... WHERE CONDITIONS
--ORDER BY ... DESC
)AS INNERQUERY ORDER BY INNERQUERY.... ASC
)
AS OUTERQUERY
ORDER BY OUTERQUERY.... DESC
它有效,但有一个显而易见的流程。如果用户要求查看最后一页并且表格中有超过1000万条记录,那么second TOP Query
必须先获得retrieve the 10 million
条记录只有这样,first top Query
才能选出Top 25
,如下所示:
SELECT * FROM
(
SELECT TOP 25 * FROM
(
SELECT TOP 10000000 ...... WHERE CONDITIONS
--ORDER BY ... DESC
)AS INNERQUERY ORDER BY INNERQUERY.... ASC
)
AS OUTERQUERY
ORDER BY OUTERQUERY.... DESC
我考虑用ROW_NUMBER OVER(....)替换上面的内容,但看起来我有同样的问题,第二个TOP语句必须得到整个结果,然后才能做where ROW_NUMBER between x and y
。
请您指出我在上述方法中的错误,并提示如何优化它?
答案 0 :(得分:0)
我目前正在使用以下代码来检索行的子集:
WITH PAGED_QRY (
SELECT *, ROW_NUMVER() OVER(ORDER BY Y) AS ROW_NO
FROM TABLE WHERE ....
)
SELECT * FROM PAGED_QRY WHERE ROW_NO BETWEEN @CURRENT_INDEX and @ ROWS_TO_RETRIEVE
ORDER BY ROW_NO
其中@current_index
和@rows_to_retrieve
(即。1
和50
)是您的分页变量。它更干净,更容易阅读。
我也尝试使用SET ROW_COUNT @ROWS_TO_RETRIEVE
,但似乎没有太大区别。
使用上面的查询并仔细研究查询的执行路径并修改/创建索引和统计数据,我已经达到了足够令人满意的结果,因此我将其作为答案。在内部查询中仅检索所需行的最初目标似乎是不可能的,如果您确实找到了方法,请告诉我。
答案 1 :(得分:0)
我们可以更多地改进上面的查询。 如果我假设@current_index是当前页码,那么我们可以将上述查询重写为:
WITH PAGED_QRY (
SELECT top (@current_index * @rows_to_retrieve) *, ROW_NUMVER()
OVER(ORDER BY Y) AS ROW_NO
FROM TABLE WHERE ....
)
SELECT TOP @ROWS_TO_RETRIEVE FROM PAGED_QRY
ORDER BY ROW_NO DESC
在这种情况下,我们的内部查询不会返回整个记录集。假设我们的page_index是3& page_size是50,那么它将只选择150行(即使我们的表包含数百/数千/数百万行)&我们也可以跳过where子句。