以最佳方式检索表格

时间:2013-03-06 22:40:32

标签: plsql count

我有一个查询,它作为一个函数的一部分运行,它产生一个完整的计数,平均值和逗号分隔列表的一行表,如下所示:

select
  (select 
    count(*)
    from vw_disp_details
    where round = 2013
    and rating = 1) applicants,
  (select 
    count(*)
    from vw_disp_details
    where round = 2013
    and rating = 1
    and applied != 'yes') s_applicants,
  (select 
    LISTAGG(discipline, ',')
    WITHIN GROUP (ORDER BY discipline) 
    from (select discipline,
          count(*) discipline_number 
          from vw_disp_details
          where round = 2013
          and rating = 1
          group by discipline)) disciplines,
  (select 
    LISTAGG(discipline_count, ',')
    WITHIN GROUP (ORDER BY discipline)
    from (select discipline,
          count(*) discipline_count
          from vw_disp_details
          where round = 2013
          and rating = 1
          group by discipline)) disciplines_count,
  (select 
    round(avg(util.getawardstocols(application_id,'1','AWARD_NAME')), 2) 
    from vw_disp_details 
    where round = 2013
    and rating = 1) average_award_score,
  (select
    round(avg(age))
    from vw_disp_details
    where round = 2013
    and rating = 1) average_age
from dual;

除了6个主要子查询外,还有23个。

返回类似这样的内容(如果是CSV):

applicants | s_applicants | disciplines               | disciplines_count | average_award_score | average_age
107        | 67           | "speed,accuracy,strength" | 3                 | 97                  | 23

现在我以编程方式交换其他表达式的where子句的“rating = 1”部分。除了“rating = 1”之外,它们都运行得相当快,大约需要90秒才能运行,这是因为vw_disp_details视图中的rating列本身是由子查询编译的:

(SELECT score
FROM read r,
eval_criteria_lookup ecl
WHERE r.criteria_id        = ecl.criteria_id
AND r.application_id       = a.lgo_application_id
AND criteria_description   = 'Overall Score'
AND type                   = 'ABC'
) reader_rank

因此,当函数运行时,这个额外的查询似乎会大大减慢一切。

我的问题是,是否有更好(更有效)的方式来运行这样的查询基本上只是一系列计数和平均值,我如何重构以优化速度,以便评级= 1查询不运行需要90秒。

3 个答案:

答案 0 :(得分:1)

您可以选择VOLIALIZE vw_disp_details VIEW。这将预先计算评级列的值。有关保存物化视图的最新方法的各种选项,您可能希望使用ON COMMIT子句,以便vw_disp_details始终正确。

查看官方文档,看看它是否适合您。 http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm

答案 1 :(得分:0)

只用一个查询完成大部分查询。而不是做:

select
  (select (count(*)                           from my_tab) as count_all,
  (select avg(age)                            from my_tab) as avg_age,
  (select avg(mypkg.get_award(application_id) from my_tab) as_avg-app_id 
from dual;

只是做:

select count(*), avg(age),avg(mypkg.get_award(application_id)) from my_tab;

然后,也许你可以为其他结果做一些联合。但这一步本身应该有所帮助。

答案 2 :(得分:0)

我能够通过做两件事来解决这个问题:创建一个只显示我需要的结果的新视图,这给了我速度的边际收益,并在该视图中移动导致子查询的where子句滞后于视图的where子句,并将子查询的结果添加为视图中的列。这仍然会返回相同的结果,这是因为表中始终存在为查询查询的每一行访问的子查询的记录。

SELECT
  a.application_id,
  util.getstatus (a.application_id) status,
  (SELECT score
    FROM applicant_read ar,
    eval_criteria_lookup ecl
    WHERE ar.criteria_id        = ecl.criteria_id
    AND ar.application_id       = a.application_id
    AND criteria_description   = 'Overall Score'        //THESE TWO FIELDS
    AND type                   = 'ABC'                  //ARE CRITERIA_ID = 15
    ) score
  as.test_total test_total
FROM application a,
  applicant_scores as
WHERE a.application_id = as.application_id(+);

成了

SELECT
  a.application_id,
  util.getstatus (a.application_id) status,
  ar.score,
  as.test_total test_total
FROM application a,
  applicant_scores as,
  applicant_read ar
WHERE a.application_id = as.application_id(+)
AND ar.application_id  = a.application_id(+)
AND ar.criteria_id     = 15;