如何从内部查询中选择第一条记录?

时间:2014-11-03 18:05:46

标签: sql oracle

我有一张桌子(称之为OBJ_EVENTS),如下所示:

EVENT_ID    OBJ_ID     EVENT_DATE     EVENT_TYPE

500         1          10/10/2010     FOO
497         1          01/05/2011     BAR
714         1          01/06/2011     BAZ
1700        2          01/01/2012     FOO
57          2          08/09/2012     BAR
12          2          08/10/2010     BAZ

重要提示 - 我的EVENT_ID未订购

我想执行一个SQL查询来显示FOO事件和bar事件之间的时差,如下所示:

OBJ_ID     FOO_TIME      BAR_TIME

1          10/10/2010    01/05/2011
2          01/01/2012    08/09/2012

当我最初编写此查询时,我的EVENT_ID已被订购,所以我做了类似的事情:

SELECT E1.OBJ_ID,
       E1.EVENT_DATE AS FOO_TIME,
       E2.EVENT_DATE AS BAR_TIME
  FROM OBJ_EVENTS E1
  JOIN OBJ_EVENTS E2
    ON (E2.EVENT_ID = (SELECT MIN(EVENT_ID)
                         FROM OBJ_EVENTS E3
                        WHERE E3.OBJ_ID = E1.OBJ_ID
                          AND E3.EVENT_DATE >= E1.EVENT_DATE
                          AND E3.EVENT_TYPE = 'BAR'))

但是,由于我不会涉及的其他项目限制,我的EVENT_ID不再按时间顺序排序,因此此查询不起作用。我也试过做order by E3.EVENT_DATE并选择row_number()= 1的位置,但这也不起作用。 Oracle抛出错误。

帮助!!!

2 个答案:

答案 0 :(得分:1)

如果每个obj_id只有一个foo事件和一个bar事件,那么您的查询过于复杂:

select ef.obj_id, ef.event_date as event_date_foo, eb.event_date as event_date_bar
from obj_events ef join
     obj_events eb
     on ef.obj_id = eb.obj_id and
        ef.event_type = 'FOO' and
        eb.event_type = 'BAR';

如果有多次出现,您需要确定自己想要的内容。这个是第一次出现:

select e.obj_id,
       min(case when e.event_type = 'FOO' then event_date end) as event_date_foo,
       min(case when e.event_type = 'BAR' then event_date end) as event_date_bar
from obj_events e
group by e.obj_id;

我假设您知道如何区分日期,因为您已经有了一个曾经有效的查询。

答案 1 :(得分:1)

所以你想要FOO事件及其随后的BAR事件。尝试使用“引导”分析函数来获得后续的BAR。

select event_type, next_type, event_date, next_date, next_date - event_date  from (
  select obj_id, event_date, event_type, 
         lead(event_type) over (partition by obj_id order by event_date) next_type,
         lead(event_date) over (partition by obj_id order by event_date) next_date
  from 
  event_test 
  where event_type in ('FOO', 'BAR')
) where event_type = 'FOO' and next_type='BAR' 

会给你这个:

1   1   FOO BAR 10/10/2010  1/5/2011    87
2   2   FOO BAR 1/1/2012    8/9/2012    221