Oracle在日期范围内加入记录或获得不在该范围内的最佳记录

时间:2013-06-27 21:01:43

标签: sql oracle11g

我有一个查询从一堆不同的表中获取数据。其中一个表有一个设备被删除的日期,我在删除它之前得到了它的最后一个读数,或者如果它没有被删除则读取最后一个读数:

        join equipment_read rd
          on rd.config_id = eq_config.config_id
         AND rd.read_dttm =
                (SELECT MAX (rd2.read_dttm)
                   FROM equipment_read rd2
                  WHERE rd2.config_id = eq_config.config_id
                    and (rd2.read_dttm < eq_hist.removal_dttm or eq_hist.removal_dttm is null))

工作正常。还有另一张表格,其中结算已经完成,而且我在那里有记录,如果在读取设备时有一张账单:

        left outer join billseg bseg
          on bseg.sa_id = sa.sa_id
         and bseg.prem_id = prem.prem_id
         and trunc(rd.read_dttm) <= bseg.end_dt and rd.read_dttm > bseg.start_dt

但是,如果设备刚刚更换,则还没有结算记录,所以我没有得到匹配。在这种情况下,我真的想获得最佳记录:选择我的read_dttm在start_dt和end_dt之间的记录 OR 获取最大start_dt记录,其中start_dt&lt; = read_dttm。

在Oracle中,我该如何进行这样的查询?在我进入所有连接之前,这是我在select的第一部分中放入CASE语句的内容吗?

以下是我可能会关注的一些数据的示例。对于我找到匹配项的记录:

read_dttm: 4/5/2013, removal_dttm = 5/3/2013
start_dt    end_dt
4/5/2013    5/7/2013   <-- get this record
3/6/2013    4/5/2013

我找不到匹配的地方:

read_dttm: 5/6/2013, removal_dttm is null
start_dt    end_dt
3/29/2013   4/25/2013   <-- get this record
2/27/2013   3/29/2013

1 个答案:

答案 0 :(得分:0)

我有一个解决方案,但它是一个好的解决方案吗? (+/-投票或其他答案会告诉我。)

重复第二个查询,一次获取日期内匹配的数据(如问题中所示):

left outer join billseg bseg1
  on bseg1.sa_id = sa.sa_id
 and bseg1.prem_id = prem.prem_id
 and trunc(rd.read_dttm) <= bseg1.end_dt and rd.read_dttm > bseg1.start_dt

和另一个匹配的地方没有(这是丑陋的,为了同时做最大和左外连接)

left outer join (select bseg_id
                      , sa_id
                      , prem_id
                      , start_dt
                      , end_dt
                  from billseg bseg2a
                 where bseg2a.start_dt = (select max (bseg2b.start_dt)
                       from billseg bseg2b
                      where bseg2b.sa_id = bseg2a.sa_id
                         and bseg2b.prem_id = bseg2a.prem_id)
                   ) bseg2
  on bseg2.sa_id = sa.sa_id
 and bseg2.prem_id = prem.prem_id
 and mr.read_dttm >= bseg2.start_dt

然后我在所选字段列表中使用case语句,如果有的话,首先选择结果,如果没有,则选择第二个结果:

 , (case when bseg1.start_dt is null then bseg2.start_dt else bseg1.start_dt end) bseg_startdt
 , (case when bseg1.end_dt is null then bseg2.end_dt else bseg1.end_dt end) bseg_enddt

可能仍然没有比赛,我想我可以忍受。我只是不知道是否做了各种各样的查询,然后选择最好的一个是一个讨厌的臭溶液或合理的选择。