0

我有一个带有大量事件类型的事务表。我希望对两种相关的事件类型进行一些分析:transit-send 和 transit-receive。该表的示例如下所示:

 ItemID | EventType | TransactionDate
--------|-----------|-----------------
 11111  | send      | 2013-07-02
 22222  | receive   | 2013-07-02
 33333  | receive   | 2013-07-03
 22222  | send      | 2013-07-03
 11111  | receive   | 2013-07-04
 55555  | send      | 2013-07-05
 22222  | receive   | 2013-07-06
 44444  | send      | 2013-07-07
 22222  | send      | 2013-07-07
 44444  | receive   | 2013-07-08
 55555  | receive   | 2013-07-09
 22222  | receive   | 2013-07-10
 33333  | send      | 2013-07-11  

我需要做的是找到每对发送-接收,其中接收是紧随发送之后的第一个:11111 在 7/2 发送出去,在 7/4 接收。22222 在 7/3 发送,然后在 7/6 接收。但是,7/2 和 7/10 也收到了 22222。

我最初尝试使用连接来获得一些快速结果:

SELECT a.ItemID, a.EventType, a.TransactionDate, b.EventType, b.TransactionDate, b.TransactionDate - a.TransactionDate AS "Days"
FROM Transactions a, Transactions b
WHERE a.ItemID = b.ItemID
AND a.EventType = 'send'
AND b.EventType = 'receive'
AND a.TransactionDate < b.TransactionDate

我知道这不会得到我想要的实际结果,但这是一个快速而肮脏的近似值。问题是它会为之后的每个接收返回多行相同的发送(注意第一个 22222 发送事务的重复):

 a.ItemID | a.EventType | a.TransactionDate | b.EventType | b.TransactionDate | Days
----------|-------------|-------------------|-------------|-------------------|------
 11111    | send        | 2013-07-02        | receive     | 2013-07-04        | 2
 22222    | send        | 2013-07-03        | receive     | 2013-07-06        | 3
 22222    | send        | 2013-07-03        | receive     | 2013-07-10        | 7
 22222    | send        | 2013-07-07        | receive     | 2013-07-10        | 3
 44444    | send        | 2013-07-07        | receive     | 2013-07-08        | 1
 55555    | send        | 2013-07-05        | receive     | 2013-07-09        | 4

谷歌建议我可以使用 LEAD 分析函数。这似乎很有希望,但鉴于我不熟悉它,我不确定如何(或是否)我可以使它适合我的模型,其中链接线不直接配对(找到 11111 的下一个交易,不管类型)。我挂断了试图将第一笔交易限制为发送,第二笔交易限制为接收。我怎样才能使这项工作?

4

1 回答 1

2

也许这会有所帮助:

select t.*,
       lead(EventType) over (partition by ItemId order by TransactionDate) as NextEventType,
       lead(TransactionDate) over (partition by ItemId order by TransactionDate) as NextEventType,
from Transactions t

然后您可以计算天数,但您需要使用子查询:

select t.*,
       (case when NextEventType = 'receive' then NextEventDate - EventDate end) as days
from (select t.*,
             lead(EventType) over (partition by ItemId order by TransactionDate) as NextEventType,
             lead(TransactionDate) over (partition by ItemId order by TransactionDate) as NextEventDate
      from Transactions t
     ) t
where t.EventType = 'send'

有两个挑战。一种情况是,如果同一项目连续两次发送,但没有接收,会发生什么情况。这将检测到这种情况并将接收分配给第二次发送。

另一个是时机。如果您在同一日期有一个事件的发送和接收,则没有足够的信息来知道哪个先发生。这可能会造成问题。您的数据没有任何此类示例。如果可能发生这种情况,解决方案是包含时间戳。

于 2013-07-17T14:22:13.897 回答