我在Oracle数据库中有一个交易表。我正在尝试为涉及多种交易类型的交付系统收集一份报告。实际上,“请求”类型可以是四个子类型之一(在此示例中为“ A”,“ B”,“ C”和“ D”),而“传递”类型可以是四个不同子类型之一类型(“ PULL”,“ PICKUP”,“ MAIL”)。从“请求”到“交付”之间可以有1到5个事务,并且“交付”类型中的许多也是中间事务。
Item | Transaction | Timestamp 001 | REQ-A | 2014-07-31T09:51:32Z 002 | REQ-B | 2014-07-31T09:55:53Z 003 | REQ-C | 2014-07-31T10:01:15Z 004 | REQ-D | 2014-07-31T10:02:29Z 005 | REQ-A | 2014-07-31T10:05:47Z 002 | PULL | 2014-07-31T10:20:04Z 002 | MAIL | 2014-07-31T10:20:06Z 001 | PULL | 2014-07-31T10:22:21Z 001 | TRANSFER | 2014-07-31T10:22:23Z 003 | PULL | 2014-07-31T10:24:10Z 003 | TRANSFER | 2014-07-31T10:24:12Z 004 | PULL | 2014-07-31T10:26:28Z 005 | PULL | 2014-07-31T10:28:42Z 005 | TRANSFER | 2014-07-31T10:28:44Z 001 | ARRIVE | 2014-07-31T11:45:01Z 001 | PICKUP | 2014-07-31T11:45:02Z 003 | ARRIVE | 2014-07-31T11:47:44Z 003 | PICKUP | 2014-07-31T11:47:45Z 005 | ARRIVE | 2014-07-31T11:49:45Z 005 | PICKUP | 2014-07-31T11:49:46Z
我需要的是像这样的报告:
Item | Start Tx | End Tx | Time 001 | REQ-A | PICKUP | 1:53:30 002 | REQ-B | MAIL | 0:24:13 003 | REQ-C | PICKUP | 1:46:30 004 | REQ-D | PULL | 0:23:59 005 | REQ-A | PICKUP | 1:43:59
我有的:
Item | Start Tx | End Tx | Time 001 | REQ-A | PULL | 0:30:49 001 | REQ-A | TRANSFER | 0:30:51 001 | REQ-A | ARRIVE | 1:53:29 001 | REQ-A | PICKUP | 1:53:30 002 | REQ-B | PULL | 0:24:11 002 | REQ-B | MAIL | 0:24:13 003 | REQ-C | PULL | 0:22:55 003 | REQ-C | TRANSFER | 0:22:57 003 | REQ-C | ARRIVE | 1:46:29 003 | REQ-C | PICKUP | 1:46:30 004 | REQ-D | PULL | 0:23:59 005 | REQ-A | PULL | 0:22:55 005 | REQ-A | TRANSFER | 0:22:57 005 | REQ-A | ARRIVE | 1:43:58 005 | REQ-A | PICKUP | 1:43:59
我正在做什么以获取数据:
SELECT Item, Transaction, nextTransaction, nextTimestamp - Timestamp FROM ( SELECT Item, Transaction, Timestamp, LEAD(Transaction, 5) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTransaction" LEAD(Timestamp, 5) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTimestamp" FROM Transactions UNION ALL SELECT Item, Transaction, Timestamp, LEAD(Transaction, 4) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTransaction" LEAD(Timestamp, 4) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTimestamp" FROM Transactions UNION ALL SELECT Item, Transaction, Timestamp, LEAD(Transaction, 3) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTransaction" LEAD(Timestamp, 3) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTimestamp" FROM Transactions UNION ALL SELECT Item, Transaction, Timestamp, LEAD(Transaction, 2) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTransaction" LEAD(Timestamp, 2) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTimestamp" FROM Transactions UNION ALL SELECT Item, Transaction, Timestamp, LEAD(Transaction, 1) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTransaction" LEAD(Timestamp, 1) OVER (PARTITION BY Item ORDER BY Timestamp) AS "nextTimestamp" FROM Transactions ) WHERE nextTransaction IS NOT NULL AND Transaction IN ('REQ-A', 'REQ-B', 'REQ-C', 'REQ-D')
我可以在脚本中手动解析它(也许这实际上是最好的做法),但是为了学习起见,我想知道是否有可能单独使用SQL实际做到这一点。
听起来您想要基于时间的第一个和最后一个事务。我认为以下是您想要的:
select item, min(transaction) keep (dense_rank first order by timestamp) as StartTx, min(transaction) keep (dense_rank last order by timestamp) as EndTx, max(timestamp) - min(timestamp) from transactions t group by item;