SQL中的分页帮助

时间:2009-02-18 20:08:59

标签: sql oracle

以下内部SELECT返回大量行(1000000+),外部SELECTs(alpha BETWEEN #startRec#AND#endRec#)用于PAGINATION 显示每页25个数据。

问题是: - 以下完成的PAGINATION非常缓慢并且减缓了整个数据的显示。所以请大家帮忙我这样做 以更好的方式分页?关于分页的编码最好。

**我很抱歉这样做,但我对分页概念很新,所以需要你的帮助。

/*********ORIGINAL QUERY ****/
SELECT
*
FROM 
(
SELECT
beta.*, rownum as alpha
FROM
(
SELECT 
p.lastname, p.firstname, porg.DEPARTMENT,
porg.org_relationship,
porg.enterprise_name,
(
SELECT 
count(*) 
FROM 
test_person p, test_contact c1, test_org_person porg 
WHERE 
p.p_id = c1.ref_id(+) 
AND p.p_id = porg.o_p_id 
$where_clause$


) AS results
FROM 
test_person p, test_contact c1, test_org_person porg
WHERE 
p.p_id = c1.ref_id(+) 
AND p.p_id = porg.o_p_id 
$where_clause$ 


ORDER BY 
upper(p.lastname), upper(p.firstname)
) beta
)
WHERE
alpha BETWEEN #startRec# AND #endRec#

我在下面尝试过的实现


(1)最内层查询..是第一个QUERY获取数据。 (2)然后,我们对上述数据进行总计COUNT。

现在,主要问题是运行查询继续进行....最后我必须强行取消它。 我觉得下面的查询中有一些东西丢失了。

另外,我开始知道在外面做COUNT是性能最好的方法。所以,请你更正下面的查询,以便我能够返回COUNT ***使用分页,rownum等数据。主要使用下面的别名,rownum和获取数据。

select * from 
( select x.* ,rownum rnum 

from ( SELECT 
count(*) as results /****2nd QUERY is OUTSIDE to get total count**/

问题在这里,我如何访问下面第一个查询中选择的数据

from ( /****1st query to SELECT data***/


SELECT 
p.lastname, p.firstname, porg.DEPARTMENT,
porg.org_relationship,
porg.enterprise_name

FROM 
t_person p, t_contact c1, t_o_person porg 
WHERE rownum <10
and
p.person_id = c1.ref_id(+) 
AND p.person_id = porg.o_person_id 



ORDER BY 
upper(p.lastname), upper(p.firstname)



) y ------------------>alias defined Y from data of the 1st query


)x ------------------>alias defined X 
where rownum <= 20 )
where rnum >= 1

7 个答案:

答案 0 :(得分:2)

要快速进行分页,您需要限制返回的查询结果。例如。在mysql中,您可以使用limit和calc_rows。

您必须检查您的数据库,但如果您没有这些帮助程序功能,那么将这些数据分解为单独的查询会更容易。

答案 1 :(得分:2)

也许我错过了什么,但你有没有考虑使用LIMIT和OFFSET条款? http://www.sql.org/sql-database/postgresql/manual/queries-limit.html

答案 2 :(得分:1)

我通常将此作为两个单独的查询,例如:

-- get page of data
SELECT *
FROM
(
    SELECT 
        p.lastname, p.firstname, porg.DEPARTMENT,
        porg.org_relationship,
        porg.enterprise_name
    FROM 
        test_person p, test_contact c1, test_org_person porg
    WHERE 
        p.p_id = c1.ref_id(+) 
        AND p.p_id = porg.o_p_id 
        $where_clause$ 
    ORDER BY 
    upper(p.lastname), upper(p.firstname)
) beta
WHERE
rownum BETWEEN #startRec# AND #endRec#

--get total count
SELECT count(*) as Count
FROM 
    test_person p, test_contact c1, test_org_person porg
WHERE 
    p.p_id = c1.ref_id(+) 
    AND p.p_id = porg.o_p_id 
    $where_clause$ 

您还可以返回结果中第一行数据的总计数,如下所示:

SELECT null, null, null, null, null, count(*) as Count
FROM 
    test_person p, test_contact c1, test_org_person porg
WHERE 
    p.p_id = c1.ref_id(+) 
    AND p.p_id = porg.o_p_id 
    $where_clause$ 

UNION ALL

SELECT *
FROM
(
    SELECT 
        p.lastname, p.firstname, porg.DEPARTMENT,
        porg.org_relationship,
        porg.enterprise_name, null
    FROM 
        test_person p, test_contact c1, test_org_person porg
    WHERE 
        p.p_id = c1.ref_id(+) 
        AND p.p_id = porg.o_p_id 
        $where_clause$ 
    ORDER BY 
    upper(p.lastname), upper(p.firstname)
) beta
WHERE
rownum BETWEEN #startRec# AND #endRec#

答案 3 :(得分:1)

您使用的数据库是什么?如果Oracle其他人建议的想法不起作用,Oracle不支持SQL的LIMIT语法。

对于Oracle,您可以使用以下语法包装查询:

SELECT * 
FROM (SELECT a.*, 
             ROWNUM rnum 
      FROM ( [your query] ) a 
      WHERE ROWNUM <= [endRow] ) 
WHERE rnum >= [startRow]

答案 4 :(得分:0)

这些专门用于ASP,但可以轻松修改: http://databases.aspfaq.com/database/how-do-i-page-through-a-recordset.html 就个人而言,当我最近需要一个分页解决方案时,我实现了“#Temp table”存储过程方法。

答案 5 :(得分:0)

我的建议是:

  • 使用lastname + firstname(按此顺序)在test_person上创建索引
  • 如果可能,删除上层函数(某些DB允许使用函数创建索引)
  • 删除外部SELECT并在客户端(不在DB中)进行分页

我怀疑必须首先解析内部子查询,如果没有合适的索引,那就太贵了。通常按计算列排序不使用索引,创建时态表等等。

干杯

答案 6 :(得分:0)

在Oracle中有几个选项:

  1. 在带有包装的内部查询中使用ROWNUM来获取分页(正如您所尝试的那样)
  2. 使用分析函数。
  3. Tom Kyte已经很好地描述了这两种方法:

    http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html

    希望这有帮助。