Oracle从一个日期列中按其结束日期选择日期间隔

e7arh2l6  于 2023-08-03  发布在  Oracle
关注(0)|答案(1)|浏览(144)

我有一个表Log,其中有DocOperDate列,每个列上有两个索引。我想按给定日期沿着按Doc分区的上一个日期选择所有行
就像

with 
Dates as (select trunc(sysdate) ate from dual),
  Log as (select 1 Doc, D.ate OperDate from dual, dates D union all
          select 1, D.ate-1 from dual, dates D union all
          select 1, D.ate-2 from dual, dates D union all
          select 2, D.ate from dual, dates D union all
          select 2, D.ate-3 from dual, dates D union all
          select 3, D.ate-4 from dual, dates D)
select A.Doc, A.OperDate, (select max(B.Operdate) from Log B where B.Doc = A.Doc and B.OperDate < A.OperDate) 
  from Log A
 where A.OperDate = trunc(sysdate) -- parameter
-- result = 2 rows

字符串
这将是对一个表的两次索引访问,另一方面,如果我使用分析函数,我认为我将失去通过索引的访问。是否可以优化此查询?

cigdeys3

cigdeys31#

不会,您不会因为使用分析函数而丢失索引访问权限。但是,为了将所有行都输入到该函数中而删除operdate上的 predicate ,您将失去访问权限,因为您无法猜测前一个日期是多远。
假设您的数据量是这样的,在这里使用索引是合适的,LOG(DOC,OPERDATE)上创建一个复合(多列)索引以方便子查询。OPERDATE上的现有索引本身将由主查询块使用。您在DOC上的索引没有用,至少对于这个目的是这样。我建议的综合指数将取代它。
但是,如果你只有一个月,并且要求一天,并且一天中的行数非常高,或者如果你在Exadata上,你可能最好不使用索引,并以这种方式编写:

SELECT *
  FROM (SELECT /*+ parallel(8) */
               doc,
               operdate,
               LAG(operdate) OVER (PARTITION BY doc ORDER BY operdate) previous_operdate
          FROM log)
  WHERE operdate = TRUNC(sysdate)

字符串
两种方法都试试,看看哪种最适合你。

相关问题