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以上の行のテーブルの親クエリは高速です。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最初と最後のサブクエリに単一の通常のインデックスを使用して、非常に効率的な 1 行の範囲スキャンを実行できると思います。

于 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 に答える