在SQL中配对事件行

时间:2018-07-02 13:14:17

标签: sql oracle

我基本上有与问题中指定的问题相同的问题:

Pairing Send and Receive Data Rows in SQL

但是我没有可以使事情变得唯一的用户/批处理组合,因此基本上具有这样的东西:

KEY   MODULE    EVENTDTTM   ACTION
-------------------------------------
1     A         01/01       SENT
2     A         02/01       RECEIVE
4     A         03/01       SENT
3     A         04/01       RECEIVE
5     A         05/01       SENT
6     A         06/01       SENT
7     A         07/01       RECEIVE
8     A         08/01       SENT

由于缺少事件,因此它们的累加不好,并且排序依赖于DTTM,而不是键顺序,但是我需要为每条记录建立一些配对,最后是这样的东西:

MODULE    CUR_KEY    NEXT_KEY   PREV_KEY
-----------------------------------------------
A         1          2          NULL
A         2          NULL       1
A         3          NULL       4
A         4          3          NULL
A         5          (NULL/7)   NULL
A         6          7          NULL
A         7          NULL       6
A         8          NULL       NULL

基本上匹配发送-接收对,以便它们根据时间戳与最接近的一对链接。只要其余顺序正确,是5指向7还是NULL并不重要。 (8)还没有任何匹配项,并且还存在相反的内容(接收未发送)。

这略高于我的认知水平,因此对您有所帮助:) 我应该加入作为cur和subquery的合适下一个对象,然后与相反的对象或...合并吗?

2 个答案:

答案 0 :(得分:1)

这是代码(使用自我联接):

select a.key as cur_key, a.module, b.key as next_key c.key as prev_key
from tab a full join tab b on a.key=b.key+1  full join tab c on and c.key = a.key-1

where a.action like 'S%'
and b.action like 'R%'

and c.action like 'S%'
and a.action like 'R%'
group by a.key

编辑: 这应该适用于“ greather”

select a.key as cur_key, a.module, b.key as next_key c.key as prev_key
    from tab a
    where a.key=  (select key 
                   from table t
                    where T.id > a.id
                    -- and (eventual binding condition)
                    and t.action like 'S%'
                    and a.action like 'R%' 
                    order by t.id
                    FETCH FIRST ROW ONLY --equivalent to select top 1
                    ) b
    and   c.key=(select key 
                   from table T
                    where T.id < a.id
                    -- and (eventual binding condition)
                    and a.action like 'S%'
                    and t.action like 'R%'
                    order by t.id desc
                    FETCH FIRST ROW ONLY --equivalent to select top 1 (that was my original idea)
                  ) c
    group by a.key

答案 1 :(得分:1)

您可以使用 <?php /** * Returns the amount of weeks into the month a date is * @param $date a YYYY-MM-DD formatted date * @param $rollover The day on which the week rolls over */ function getWeeks($date, $rollover) { $cut = substr($date, 0, 8); $daylen = 86400; $timestamp = strtotime($date); $first = strtotime($cut . "00"); $elapsed = ($timestamp - $first) / $daylen; $weeks = 1; for ($i = 1; $i <= $elapsed; $i++) { $dayfind = $cut . (strlen($i) < 2 ? '0' . $i : $i); $daytimestamp = strtotime($dayfind); $day = strtolower(date("l", $daytimestamp)); if($day == strtolower($rollover)) $weeks ++; } return $weeks; } // echo getWeeks("2011-06-11", "sunday"); //outputs 2, for the second week of the month ?> LAG函数。

SQL Fiddle

Oracle 11g R2架构设置

LEAD

查询1

CREATE TABLE Table1
    ("KEY" int, "MODULE" varchar2(1), "EVENTDTTM" timestamp, "ACTION" varchar2(7))
;

INSERT ALL 
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (1, 'A', '01-Jan-2018 12:00:00 AM', 'SENT')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (2, 'A', '01-Feb-2018 12:00:00 AM', 'RECEIVE')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (4, 'A', '01-Mar-2018 12:00:00 AM', 'SENT')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (3, 'A', '01-Apr-2018 12:00:00 AM', 'RECEIVE')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (5, 'A', '01-May-2018 12:00:00 AM', 'SENT')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (6, 'A', '01-Jun-2018 12:00:00 AM', 'SENT')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (7, 'A', '01-Jul-2018 12:00:00 AM', 'RECEIVE')
    INTO Table1 ("KEY", "MODULE", "EVENTDTTM", "ACTION")
         VALUES (8, 'A', '01-Aug-2018 12:00:00 AM', 'SENT')
SELECT * FROM dual
;

Results

SELECT   KEY , 
         module , 
         action , 
         CASE 
                  WHEN LEAD(action) OVER ( PARTITION BY module ORDER BY eventdttm ) = 'RECEIVE' 
                  AND      action = 'SENT' THEN LEAD(KEY) OVER ( PARTITION BY module ORDER BY eventdttm ) 
         END AS NEXT_KEY , 
         CASE 
                  WHEN LAG(action) OVER ( PARTITION BY module ORDER BY eventdttm ) = 'SENT' 
                  AND      action = 'RECEIVE' THEN LAG(KEY) OVER ( PARTITION BY module ORDER BY eventdttm ) 
         END AS PREV_KEY 
FROM     table1 
ORDER BY KEY