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

Sql 如何在不同表中的条目之后找到表中的下一个条目?,sql,oracle,Sql,Oracle,我想我只是遇到了一个问题,我不能把我的大脑集中在这个问题上,但我也不确定这是否真的可能 我有两张桌子。一个是事务日志。另一个是项目历史记录。我需要知道在设置项目进程状态时是否发生了事务,这样我就可以计算未设置该属性的所有事务 表中相关列的简化视图: 交易: event_id event_type event_item_id event_timestamp 项目历史记录: item_id item_process_status item_history_timestamp 我需要做的是统计'7

我想我只是遇到了一个问题,我不能把我的大脑集中在这个问题上,但我也不确定这是否真的可能

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

表中相关列的简化视图:

交易:

event_id
event_type
event_item_id
event_timestamp
项目历史记录:

item_id
item_process_status
item_history_timestamp
我需要做的是统计'71',72',74个事件中的所有事件类型,其中事件\u项\u id的下一个条目,即项目\u历史\u时间戳是事件\u时间戳没有项目\u进程\u状态之后项目\u id的第一个项目\u历史条目。我想我应该使用LEAD、OVER或其他一些分析函数,但我对分析函数还不够熟悉,不知道如何构造这样的查询。过去我唯一一次使用它们是在一张桌子上

示例架构:

CREATE TABLE item (
  item_id VARCHAR(5),
  item_process_status VARCHAR(2)

CREATE TABLE item_history (
  item_id VARCHAR(5),
  item_process_status VARCHAR(2),
  item_history_timestamp TIMESTAMP
);

CREATE TABLE event (
  event_id VARCHAR(5),
  event_type VARCHAR(2),
  event_item_id VARCHAR(5),
  event_timestamp TIMESTAMP
);

INSERT INTO item VALUES('10233', 'IP');
INSERT INTO item VALUES('40421', NULL);
INSERT INTO item VALUES('44026', NULL);
INSERT INTO item VALUES('55329', NULL);

INSERT INTO item_history VALUES('55329', NULL, TO_TIMESTAMP('2013-10-02 13:37', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('40421', NULL, TO_TIMESTAMP('2013-10-02 15:44', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('10233', 'OR', TO_TIMESTAMP('2013-10-03 08:21', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('10233', 'IP', TO_TIMESTAMP('2013-10-03 09:15', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('44026', NULL, TO_TIMESTAMP('2013-10-04 16:28', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('44026', 'IP', TO_TIMESTAMP('2013-10-05 11:56', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('40421', NULL, TO_TIMESTAMP('2013-10-06 10:03', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('10233', NULL, TO_TIMESTAMP('2013-10-06 14:19', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('55329', 'IP', TO_TIMESTAMP('2013-10-07 08:36', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('10233', NULL, TO_TIMESTAMP('2013-10-08 12:52', 'YYYY-MM-DD HH24:MI'));
INSERT INTO item_history VALUES('44026', NULL, TO_TIMESTAMP('2013-10-09 11:56', 'YYYY-MM-DD HH24:MI'));

INSERT INTO event VALUES ('00001', '71', '55329', TO_TIMESTAMP('2013-10-02 13:44', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00002', '69', '40421', TO_TIMESTAMP('2013-10-03 17:23', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00003', '43', '10233', TO_TIMESTAMP('2013-10-03 22:56', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00004', '52', '44026', TO_TIMESTAMP('2013-10-04 19:12', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00005', '72', '10233', TO_TIMESTAMP('2013-10-04 20:32', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00006', '74', '40421', TO_TIMESTAMP('2013-10-05 17:06', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00007', '71', '44026', TO_TIMESTAMP('2013-10-06 11:09', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00008', '80', '10233', TO_TIMESTAMP('2013-10-06 16:29', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00009', '71', '55329', TO_TIMESTAMP('2013-10-07 13:44', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00010', '69', '40421', TO_TIMESTAMP('2013-10-07 17:23', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00011', '43', '10233', TO_TIMESTAMP('2013-10-07 22:56', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00012', '52', '44026', TO_TIMESTAMP('2013-10-08 19:12', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00013', '72', '10233', TO_TIMESTAMP('2013-10-08 20:32', 'YYYY-MM-DD HH24:MI'));
INSERT INTO event VALUES ('00014', '74', '40421', TO_TIMESTAMP('2013-10-09 17:06', 'YYYY-MM-DD HH24:MI'));
预期查询输出: 事件| id |计数* 71 | 2 72 | 1 74 | 2

这里的技巧是,前71个事件00001不被计算,因为项目55329在下一个项目历史记录条目中具有流程状态,而事件00013不被计算,因为项目当前具有流程状态,并且它发生在项目10233的最后一个事务之后


请注意,这不适用于SQLfiddle,因为站点显然没有TO_时间戳功能。

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

  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)

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

  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上提供示例数据和预期输出的另一个好处是,当你把所有这些都放进去的时候,你已经掌握了自己解决问题所需的一切——在这种情况下,你可以发布自己问题的答案并接受它——你可能会获得一些解决问题的选票你自己。:-分享和享受。确实如此:我想你忘了在SQLFiddle从默认的MySQL改为Oracle。请提供示例数据和预期输出,在SQLFiddle上提供示例数据和预期输出的另一个好处是,当你把所有这些都放进去的时候,你已经掌握了自己解决问题所需的一切——在这种情况下,你可以发布自己问题的答案并接受它——你可能会获得一些解决问题的选票你自己。:-分享和享受。确实如此:我想你忘了在SQLFiddle.Yikes上从默认的MySQL改为Oracle吧!这就成功了。事实上,我又加了一个包装纸,把它加入到每月的总数中,但这并没有改变多少。哎呀!这就成功了。实际上,我添加了另一个包装器,将其计入每月总数,但这并没有改变多少。