0

我将尝试解释这一点(简化)...

我有一个查询,它主要使用数据范围作为限定符从表中收集数据;

select parent_order_id, order_id, order_dt_tm
from orders
where order_dt_tm between to_date("2013-05-30 00:00:00", 'YYYY-MM-DD HH24:MI:SS') AND to_date("2013-05-30 23:59:59")

所以,order_id 是唯一的,而 parent_order_id 有很多子 order_id 的

parent_order_id    order_id    order_dt_tm
---------------    --------    -----------
111.00             112.00      2013-05-29 06:00:00
111.00             113.00      2013-05-29 18:00:00
111.00             114.00      2013-05-30 06:00:00
111.00             115.00      2013-05-30 18:00:00  
111.00             116.00      2013-05-31 06:00:00
111.00             117.00      2013-05-31 18:00:00

我的问题是我需要上述查询的结果加上开始日期之前的最高结果和结束日期之后的最低结果。基本上我希望我的结果集是;

parent_order_id    order_id    order_dt_tm
---------------    --------    -----------
111.00             113.00      2013-05-29 18:00:00
111.00             114.00      2013-05-30 06:00:00
111.00             115.00      2013-05-30 18:00:00  
111.00             116.00      2013-05-31 06:00:00

我不知道运行时的日期范围或异常值的限定符,我只能通过最高和最低。

这张表上有很多数据,我尝试了以下类似的方法来获得之前的最高值。

select parent_order_id, order_id, order_dt_tm
from orders
where order_dt_tm between to_date("2013-05-30 00:00:00", 'YYYY-MM-DD HH24:MI:SS') AND to_date("2013-05-30 23:59:59")
    or order_id = 
             (select distinct FIRST_VALUE(order_id) OVER (PARTITION BY parent_order_id ORDER BY order_id DESC
             from orders
             where order_dt_tm < to_date("2013-05-30 00:00:00", 'YYYY-MM-DD HH24:MI:SS')
             )

问题是; 它很慢......在一个包含 5M+ 行的表中的父查询及其所有其他 quals 很快。order_dt_tm 是索引的一部分。但无论我以何种方式应用资格来获取异常值,它都会变得非常缓慢。

此外,我不确定我是否始终可以确定 order_id 是日期的最高值。真的应该按日期和时间来实现。

谢谢你的帮助!

4

2 回答 2

1

最有效的查询可能是这样的:

-- last row of previous day
SELECT parent_order_id, order_id, order_dt_tm
  FROM (SELECT parent_order_id, order_id, order_dt_tm
          FROM orders
         WHERE order_dt_tm < :date_start
         ORDER BY order_dt_tm DESC)
  WHERE ROWNUM = 1)
UNION ALL
<your_query>
UNION ALL
-- first row of the next day
SELECT parent_order_id, order_id, order_dt_tm
  FROM (SELECT parent_order_id, order_id, order_dt_tm
          FROM orders
         WHERE order_dt_tm > :date_end
         ORDER BY order_dt_tm)
  WHERE ROWNUM = 1)

我认为单个常规索引order_dt_tm可用于第一个和最后一个子查询,以执行非常有效的单行范围扫描。

于 2013-05-30T13:45:17.760 回答
0

我会使用滞后和领先

select parent_order_id, order_id, order_dt_tm
from
(
    select parent_order_id
    ,      order_id
    ,      order_dt_tm
    ,      lag(order_dt_tm) over (order by order_dt_tm)  prev_order_dt_tm
    ,      lead(order_dt_tm) over (order by order_dt_tm) next_order_dt_tm
    from   orders
)
where  next_order_dt_tm >= to_date('2013-05-30 00:00:00', 'YYYY-MM-DD HH24:MI:SS')  -- start_date of range
and    prev_order_dt_tm <= to_date('2013-05-30 23:59:59', 'YYYY-MM-DD HH24:MI:SS')  -- end_date of range 
于 2013-05-30T13:49:54.353 回答