在我的oracle数据库中,我得到了一个包含多行存储事件信息消息的表。
每个事件都是特定的事件类型。此外,每个事件都有一个列值“OPEN”或“CLOSED”,表示事件消息是打开还是关闭消息。
现在我需要确定所有“OPEN”消息并获得相应的“CLOSED”。以我的表为例:
+----+----------+-----------+-------------------+-----------------------------+--------+
| ID | SENDERID | EventType | EventDescription | Date | Status |
+----+----------+-----------+-------------------+-----------------------------+--------+
| 1 | 111 | EventTyp2 | Something happend | 27.03.17 12:56:10,000000000 | CLOSED |
+----+----------+-----------+-------------------+-----------------------------+--------+
| 2 | 111 | EventTyp1 | Something happend | 20.03.17 00:12:29,666000000 | CLOSED |
+----+----------+-----------+-------------------+-----------------------------+--------+
| 3 | 111 | EventTyp2 | Something happend | 19.03.17 00:12:31,255000000 | OPEN |
+----+----------+-----------+-------------------+-----------------------------+--------+
| 4 | 222 | EventTyp2 | Something happend | 19.03.17 00:12:31,255000000 | CLOSED |
+----+----------+-----------+-------------------+-----------------------------+--------+
| 5 | 111 | EventTyp1 | Something happend | 17.03.17 11:32:42,452000000 | OPEN |
+----+----------+-----------+-------------------+-----------------------------+--------+
| 6 | 222 | EventTyp2 | Something happend | 17.03.17 11:32:36,185000000 | OPEN |
+----+----------+-----------+-------------------+-----------------------------+--------+
有没有办法获得一个结果,该结果将开启和关闭日期一起返回事件类型和描述?
我不知道如何说“搜索包含相同EventTyp和'最近'日期的CLOSING行,因为这必须是结束事件消息'。
修改:
结果应该与以下示例相同
+----+-----------+-----------+-------------------+-----------------------------+-----------------------------+
| ID | Sender ID | EventType | EventDescription | Date Open | Date Closed |
+----+-----------+-----------+-------------------+-----------------------------+-----------------------------+
| 1 | 111 | EventTyp2 | Something happend | 19.03.17 00:12:31,255000000 | 27.03.17 12:56:10,000000000 |
+----+-----------+-----------+-------------------+-----------------------------+-----------------------------+
| 2 | 111 | EventTyp1 | Something happend | 17.03.17 11:32:42,452000000 | 20.03.17 00:12:29,666000000 |
+----+-----------+-----------+-------------------+-----------------------------+-----------------------------+
| 3 | 222 | EventTyp2 | Something happend | 17.03.17 11:32:36,185000000 | 19.03.17 00:12:31,255000000 |
+----+-----------+-----------+-------------------+-----------------------------+-----------------------------+
我已经尝试过以下操作,但是你可以假设我为一个“OPEN”行获得所有匹配的“CLOSED”行。 (我已对查询进行了匿名处理)
WITH EventOpen AS
(
SELECT
event.ID,
event.SENDERID,
event.DATE,
event.STATUS,
event.EVENTTYPID,
event.EVENTDESCRIPTION
FROM
EVENTTABLE event
WHERE
event.STATUS = 'OPEN'
),
EventClose AS
(
SELECT
event.ID,
event.SENDERID,
event.DATE,
event.STATUS,
event.EVENTTYPID,
event.EVENTDESCRIPTION
FROM
EVENTTABLE event
WHERE
event.STATUS = 'CLOSED'
),
SELECT
eo.ID,
eo.SENDERID
eo.EVENTDESCRIPTION
eo.EVENTTYPID
eo.DATE AS OPENEDAT,
ec.DATE AS CLOSEDAD,
FROM
EventOpen eo
LEFT OUTER JOIN EventClose ec
ON eo.EVENTTYPID = ec.EVENTTYPID
AND eo.SENDERID = ec.SENDERID
AND eo.ID < ec.ID AND (eo.DATE < ec.DATE)
EDIT2: 感谢匿名,我错过了一个重要的专栏:senderid。每个事件都有一个特定的源,由senderid
定义答案 0 :(得分:1)
使用lead()分析函数来匹配OPEN和CLOSE事件:
select *
from (
select
ev.EVENTTYPID,
ev.SENDERID,
ev.DATE open_date,
lead(ev.DATE) over
(partition by ev.EVENTTYPID, ev.SENDERID order by ev.DATE) close_date,
ev.EVENTDESCRIPTION open_description,
lead(ev.EVENTDESCRIPTION) over
(partition by ev.EVENTTYPID, ev.SENDERID order by ev.DATE) close_description,
ev.STATUS
from EVENTTABLE ev
)
where STATUS = 'OPEN'
order by open_date
如果您不想查询尚未关闭的事件,请添加
and close_date is not null
到外where
子句。
答案 1 :(得分:1)
@ fen1x的优秀解决方案有一点变化,涵盖重复的OPEN事件。
此外,在state
上检查并测试了潜在客户CLOSE
,即处理已关闭=或NULL
(即处理仍在进行中)。国家OPEN
的重复案例受到了压制。
select
EVENTTYPE, SENDERID, OPEN_DATE, CLOSE_DATE, OPEN_DESCRIPTION, CLOSE_DESCRIPTION, NEXT_STATUS
from (
select
ev.EVENTTYPE,
ev.SENDERID,
ev.trans_d open_date,
lead(ev.trans_d) over
(partition by ev.EVENTTYPE, ev.SENDERID order by ev.trans_d) close_date ,
-- check for duplicated close
lead(ev.status) over
(partition by ev.EVENTTYPE, ev.SENDERID order by ev.trans_d) next_status,
ev.EVENTDESCRIPTION open_description,
lead(ev.EVENTDESCRIPTION) over
(partition by ev.EVENTTYPE, ev.SENDERID order by ev.trans_d) close_description,
ev.STATUS
from tab ev
)
where STATUS = 'OPEN' and (NEXT_STATUS = 'CLOSED' or NEXT_STATUS is NULL)
order by open_date
请注意,这是简单的清洁;如果EVENTTYPE
和SENDERID
内有重复,则最后OPEN
与第一个CLOSE
相关联 - 所有其他重复事件都将被忽略。
答案 2 :(得分:0)
这个在SQL SERVER上运行,在ORACLE中应该也很有用
select position = DENSE_RANK () over (order by EventType, SenderID, Date),*
into #t
from EVENTTABLE event
where Status ='OPEN'
order by EventType, SenderID, Date
select t.*, CloseDate = ev.DatE
from #t t
left join EVENTTABLE ev on
ev.EventType = t.EventType and
ev.SenderID = t.SenderID and
ev.Status = 'OUT' and
ev.Date > t.Date and
ev.Date < (select Date from #t where position = t.position+1)