如何在不同表中输入后找到表中的下一个条目?

时间:2013-11-15 20:24:16

标签: sql oracle

我想我只是遇到了一个无法解决问题的问题,但我也不确定它是否真的可能。

我有两张桌子。一个是交易日志。另一个是项目历史。我需要知道在设置项目进程状态时是否发生了事务,以便我可以计算未设置该属性的所有事务。

表格中相关列的简化视​​图:

交易:

event_id
event_type
event_item_id
event_timestamp

item_history:

item_id
item_process_status
item_history_timestamp

我需要做的是统计所有event_type IN ('71', '72, '74)个事件,其中event_item_id的下一个条目(即item_history_timestampitem_history的{​​{1}}条目} item_id之后}没有event_timestamp。我认为我应该使用LEAD,OVER或其他一些分析功能,但我对分析功能不太熟悉,不知道如何构建这样的查询。我过去唯一一次使用它们就是在一张桌子上。

示例架构:

item_process_status

预期的查询输出:     event_id |计数(*)     71 | 2     72 | 1     74 | 2

这里的技巧是第71个(事件00001)不计算,因为项目55329在下一个项目历史记录条目中具有过程状态,事件00013不计数,因为该项目当前具有过程状态并且它发生在项目10233的最后一笔交易。

请注意,这不适用于SQLfiddle,因为该网站显然没有TO_TIMESTAMP函数。

1 个答案:

答案 0 :(得分:1)

首先,为项目构建完整的状态历史记录:

  select
    item_id,
    (
      lag(until_time) over (
        partition by item_id 
        order by until_time
      )
    ) since_time,
    until_time,
    item_process_status
  from (
        select 
          item_id, 
          item_history_timestamp until_time,
          item_process_status
        from 
          item_history
      union all
        select 
          item_id,
          systimestamp until_time,
          item_process_status
        from item
  )

然后将其与事件历史记录联系起来,以获取每个状态历史记录片段发生的事务并应用过滤器:

  select
    full_history.item_id,
    full_history.since_time,
    full_history.until_time, 
    full_history.item_process_status,
    item_events.event_type,
    item_events.event_timestamp,
    item_events.event_id
  from 
    (
      select
        item_id,
        (
          lag(until_time) over (
            partition by item_id 
            order by until_time
          )
        ) since_time,
        until_time,
        item_process_status
      from (
          select 
            item_id, 
            item_history_timestamp until_time,
            item_process_status
          from 
            item_history
        union all
          select 
            item_id,
            systimestamp           until_time,
            item_process_status
          from 
            item
      )
    )
          full_history,
    event item_events
  where
    item_events.event_item_id = full_history.item_id
    and
    item_events.event_timestamp < full_history.until_time
    and
    (
      item_events.event_timestamp >= full_history.since_time
      or
      (full_history.since_time is null)
    )
    and 
    item_events.event_type in ('71','72','74') 
    and
    (full_history.item_process_status is null)

SQLFiddle exmaple