如果有的话,Oracle会找到以前的记录

时间:2013-05-29 22:56:44

标签: sql oracle select plsql oracle11g

我有一个查询,根据一些资格获得前两个记录。这样可以正常工作,但如果没有至少三个记录则找不到项目。所以,我需要在下面修改我的查询,但我不太确定如何。

select t1.index
     , t1.date
     , t1.flag
     , t2.date
     , t2.flag
     , t3.date
     , t3.flag
from table t1
left outer join table t2
  on t2.index = t1.index
left outer join table t3
  on t3.index = t1.index
where t1.flag = '30'
  and t1.date >= to_date('05/08/2013','MM/DD/YYYY')
  and t2.date = (select max(t2a.date) from table t2a
                 where t2a.index = t1.index
                   and t2a.date < t1.date)
  and t3.date = (select max(t3a.date) from table t3a
                 where t3a.index = t1.index
                   and t3a.date < t2.date)

所以,只要至少有三个记录具有相同的索引字段,它就会找到最近的记录(t1),然后找到下一个最近的记录(t2),然后找到那个之后的记录(t3) ,按日期排序。

我正在处理滞后函数并且根据我的复杂链接和排序没有得到任何可靠的东西(这个例子是愚蠢的,因为索引在一个表中,日期在另一个表中通过第三个表链接。 )

基本上,我希望where语句“找到与我们已经找到的标准相匹配的最大日期,或者如果你没有找到更多的标准,那么那就没问题,并返回你找到的内容。”我如何编码“或者如果你没有找到更多的东西”?

3 个答案:

答案 0 :(得分:1)

这是一种方式

select t1.index
     , t1.date
     , t1.flag
     , t2.date
     , t2.flag
     , t3.date
     , t3.flag
from table t1
left outer join table t2
  on t2.index = t1.index
  and t2.date = (select max(t2a.date) from table t2a
                 where t2a.index = t1.index
                   and t2a.date < t1.date)
left outer join table t3
  on t3.index = t1.index
  and t3.date = (select max(t3a.date) from table t3a
                 where t3a.index = t1.index
                   and t3a.date < t2.date)
where t1.flag = '30'
  and t1.date >= to_date('05/08/2013','MM/DD/YYYY')

另一种方法是将你的和条款包装在T2和T3上并在t2链接上使用OR t2.date is null并在t3上使用T3.date is null

至于原因:左边连接只有当它们存在于T1中时才从T2和t3返回记录。哪个不会找到最大值因此它通过在连接或在其中应该工作的where子句中评估null来返回“Null”。但是,这假设在记录存在时始终填充“日期”字段。

答案 1 :(得分:0)

这里的问题是你使用外连接加入到t2和t3,然后在WHERE子句中加入条件。如果将这些条件移到JOIN子句中,这应该可以解决问题。

作为替代方法,您可以使用分析函数尝试此查询,以从查询中删除MAX函数。这样可以简化逻辑并使其性能更好。

with my_table as (
  select 
    index, 
    date, 
    flag,
    row_number() over (partition by index order by date desc) as rown
  from table
)
select t1.index
     , t1.date
     , t1.flag
     , t2.date
     , t2.flag
     , t3.date
     , t3.flag
from table t1
left outer join table t2
  on (t2.index = t1.index and t2.rown = t1.rown + 1)
left outer join table t2
  on (t3.index = t2.index and t3.rown = t2.rown + 1)
where t1.flag = '30'
  and t1.date >= to_date('05/08/2013','MM/DD/YYYY')

答案 2 :(得分:0)

您可能想要进入LEAD和LAG分析函数。它们的工作方式与您的问题中的说法略有不同,返回(对于LEAD)“下一个”和“下一个+ 1”值作为同一行的一部分而不是单独的行,但也许它们会证明是有用的。示例小提琴here

分享并享受。