Этот вопрос практически идентичен другому, который я недавно задавал, с тем очень важным отличием, что эти транзакции являются кредитными транзакциями и, следовательно, элементы могут повторно появляться в данных несколько раз. Вот почему я сейчас использую LEAD
. С этим разъяснением я повторяю свой вопрос ниже.
У меня есть таблица транзакций в базе данных 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.
Чтобы уточнить бит «ссуды», в этой таблице есть другие транзакции для возвратов и других форм обработки, которые не имеют отношения к этому отчету, помимо существующих как другие типы транзакций. Как только элемент возвращен, он может снова пройти цикл запроса. Например, для элемента 001
он может следовать циклу элемента 002
(REQ -> MAIL), затем он может получить транзакцию «Нет на полке», или ссуду без запроса, или несколько других вариантов использования. Затем он может вернуться через цикл REQ -> PICKUP или цикл REQ-> PULL.
REQ
? Дополнительные данные (в Fiddle?), чтобы продемонстрировать новую проблему и ожидаемые результаты, помогут. Я тоже не понимаю, как вашаlead
версия справится с этим. - person Alex Poole   schedule 01.08.2014