Возвращает продолжительность элемента из транзакций, многие ко многим, SQL - PullRequest
0 голосов
/ 16 июня 2020

Надеюсь, я смогу получить некоторую помощь в этом.

Ситуация

Есть две входящие станции и одна исходящая станция. Элементы сканируются внутрь и наружу. Мне нужно знать, как долго предмет находился на станции. Предположим, что «на станции» - это время между сканированием входящей даты и исходящим сканированием даты.

Проблема

  1. Элемент может (случайно) отсканирован несколько раз на любую станцию ​​(для этого я думал определить, было ли сканирование сделано в тот же день (без учета часов), затем вернуть самое раннее сканированное время)

  2. Элемент может приходить и выходить со станции несколько раз (многократное сканирование на входе и выходе)

  3. Если элемент был отсканирован в оба входящих местоположения, необходимо получить самое раннее время

Образец данных .. здесь мы go

╔═════════╦════════╦══════════════════╦════════════════╦══════════╗
║ Row_num ║ ItemID ║      Dates       ║  LocationName  ║   Type   ║
╠═════════╬════════╬══════════════════╬════════════════╬══════════╣
║       1 ║ ItemA  ║ 1/7/20 12:49 PM  ║ Outgoing_Loc   ║ Outgoing ║
║       2 ║ ItemA  ║ 1/2/20 7:29 AM   ║ Incoming_Loc_A ║ Incoming ║
║       3 ║ ItemB  ║ 1/3/20 11:01 AM  ║ Outgoing_Loc   ║ Outgoing ║
║       4 ║ ItemB  ║ 1/2/20 4:57 PM   ║ Incoming_Loc_B ║ Incoming ║
║       5 ║ ItemB  ║ 1/2/20 5:01 PM   ║ Incoming_Loc_A ║ Incoming ║
║       6 ║ ItemB  ║ 12/12/19 5:58 PM ║ Outgoing_Loc   ║ Outgoing ║
║       7 ║ ItemB  ║ 12/12/19 5:57 PM ║ Outgoing_Loc   ║ Outgoing ║
║       8 ║ ItemB  ║ 5/20/19 10:19 AM ║ Outgoing_Loc   ║ Outgoing ║
║       9 ║ ItemC  ║ 1/9/20 9:20 AM   ║ Outgoing_Loc   ║ Outgoing ║
║      10 ║ ItemC  ║ 1/2/20 6:42 PM   ║ Incoming_Loc_A ║ Incoming ║
║      11 ║ ItemC  ║ 12/20/19 5:54 AM ║ Outgoing_Loc   ║ Outgoing ║
║      12 ║ ItemC  ║ 10/10/19 6:13 PM ║ Outgoing_Loc   ║ Outgoing ║
║      13 ║ ItemC  ║ 10/5/19 7:00 PM  ║ Incoming_Loc_A ║ Incoming ║
║      14 ║ ItemC  ║ 7/16/19 9:18 AM  ║ Outgoing_Loc   ║ Outgoing ║
╚═════════╩════════╩══════════════════╩════════════════╩══════════╝

Я попытался представить все типы проблем в таблице, распределенной по различным элементам.

Идеальная транзакция - ItemA , это так просто и чисто, если бы все они были такими, я мог бы просто объединить таблицы и перетащить их в отдельные столбцы.

ItemB , вы заметите, что этот был отсканирован в оба входящих местоположения, но мне нужно вернуть только одно - самое раннее из этого пакета. Кроме того, необходимо вернуть входящий, который следует за самым старым исходящим (12.12.19) и перед последним исходящим (1/3/20).

Item C, аналогично последнему утверждению для ItemB, этот элемент входил и выходил из локаций дважды. Требуется получить пару входящих и исходящих сообщений, которая имеет наибольший смысл в хронологическом порядке.

Я не знаю, насколько это сложно понять, но мне трудно найти решение для этого. Я не уверен, как втиснуть входящую дату между исходящей.

Пример вывода: Нужно узнать, сколько дней каждый предмет находился на станции. Если элемент входил и выходил несколько раз, необходимо объединить входящие и исходящие элементы в пары, которые имеют наибольший смысл в хронологическом порядке. Например, в элементе C есть несколько дат входа и выхода, но мне нужны только даты, у которых есть пара начало и конец.

+--------+-----------------+------------------+-----------------+
| ItemID |    Incoming     |     Outgoing     | Days in Station |
+--------+-----------------+------------------+-----------------+
| ItemA  | 1/2/20 7:29 AM  | 1/7/20 12:49 PM  | 5.00            |
| ItemB  | 1/2/20 4:57 PM  | 1/3/20 11:01 AM  | 1.00            |
| ItemC  | 1/2/20 6:42 PM  | 1/9/20 9:20 AM   | 7.00            |
| ItemC  | 10/5/19 7:00 PM | 10/10/19 6:13 PM | 5.00            |
+--------+-----------------+------------------+-----------------+

1 Ответ

1 голос
/ 17 июня 2020

Это проблема промежутков и островов. Подход состоит в том, чтобы определить группы, используя кумулятивную сумму, которая увеличивается для каждой входящей записи, и использовать ее для агрегирования:

select
    itemID,
    min(dates) incoming,
    max(dates) outgoing,
    datediff(second, min(dates), max(dates)) / 60.0 / 60 / 24 days_in_station
from (
    select
        t.*,
        sum(case when type = 'Incoming' then 1 else 0 end)
            over(partition by itemID order by dates) grp
    from mytable t
) t
group by itemID, grp

В вашем вопросе не указано, что должно произойти, когда входящие / исходящие записи не чередуются должным образом для данный предмет. Вот как запрос будет обрабатывать это:

  • если есть две последовательные входящие записи, это генерирует строку в наборе результатов, где входящие и исходящие даты идентичны, а дни на станции равны 0

  • при наличии двух или более последовательных исходящих записей учитывается только последняя

Их можно настроить, если больше подробности по требованию предоставлены.

...