不使用union就优化查询

时间:2017-10-26 08:47:43

标签: sql oracle optimization union

我有以下查询,它是从匿名块生成的。如果需要,我也可以更改匿名块。 以下查询结果是在2010年和1月份提到的,但我这几个月都在做。通过这种方式,我希望从2009年到2017年逐年运行此查询。 var d1 = moment.duration(point1Time, 'hours'); var asSecs = d1.asSeconds() var HHMMSS = secondsToHHMMSS(asSecs) function pad(num) { return ("0"+num).slice(-2); } function secondsToHHMMSS(secs) { var hours = Math.floor(secs / 3600); secs = secs%3600; var minutes = Math.floor(secs / 60); secs = secs%60; return pad(hours)+":"+pad(minutes)+":"+pad(secs); } 的值是不同的,有47个值。因此,对于1月份,它将产生47条记录。

查询每年需要花费超过10分钟的时间才能同时运行。有没有其他方法可以优化此查询并使其成为单个查询? 我每次都使用rownum获取第一条记录。

我没有任何列的索引。

ID_REC

2 个答案:

答案 0 :(得分:2)

row_number()partition by

一起使用
select id_rec, month_id, name, load_sdt, load_id
  from (select id_rec, month_id, name, load_sdt, load_id, 
               row_number() over (partition by id_rec order by null) as rn
          from test_rec_list 
          where month_id = 201001)
  where rn = 1;

如果您只对特定的and id_rec in (1, 2, 3, 5....)感兴趣,请将where添加到id_rec子句。

您还可以将where month_id = 201001更改为month_id between ... and ...并在month_id中加入partition by,以便在一个查询中完成所有操作。

如果您有任何密钥,可能order by null或日期,请将load_id更改为正确的顺序。

修改:根据您的评论,您的查询应该是:

select entity_id,month_id,sys_db_name,sys_load_dts,sys_load_id 
  from (select entity_id,month_id,sys_db_name,sys_load_dts,sys_load_id, 
               row_number() over (partition by entity_id, month_id order by rowid) as rn
          from int_pub_edw.dm_cust_purch_fl 
          where month_id between 201001 and 201012 and entity_id between 0 and 48)
  where rn = 1;

请勿使用row_number()两次,不要省略where rn = 1,这非常重要,此处我们每个ID /月只能获得一行。

表被点击一次,没有联合,一个查询中的所有内容,如果列entity_idmonth_id上有索引,它应该很快。

答案 1 :(得分:1)

这个怎么样:

SELECT DISTINCT
    ID_REC, MONTH_ID, 
    FIRST_VALUE(NAME) OVER (PARTITION BY ID_REC, MONTH_ID ORDER BY ROWID) AS NAME, 
    FIRST_VALUE(LOAD_SDT) OVER (PARTITION BY ID_REC, MONTH_ID ORDER BY ROWID) LOAD_SDT, 
    FIRST_VALUE(LOAD_ID) OVER (PARTITION BY ID_REC, MONTH_ID ORDER BY ROWID) AS LOAD_ID
from TEST_REC_LIST 
where month_id = 201001 
   and ID_REC BETWEEN 0 and 48;