Заливка журналов автоматизации с помощью Postgres - PullRequest
0 голосов
/ 05 октября 2018

Я не мог придумать хорошего названия для моего вопроса.У меня есть автоматизированный склад с конвейерами, движущимися коробками.Каждая коробка имеет уникальный номер посылки.Есть десятки сканеров, говорящих о том, куда идти.Каждый раз, когда сканер видит поле, он создает в таблице две строки (Sort и Confirm), которые выглядят следующим образом:

    time          scanner    type    parcel
12:00:19.635        s15      Sort     83128
12:00:20.3          s15      Confirm  83128
12:02:05.857        s18      Sort     94387 
12:02:07.692        s18      Confirm  94387

Итак, каждый уникальный номер посылки и каждый уникальный сканер имеет много записей.Как я могу написать запрос, который скажет мне, какие посылки начали свое путешествие (видно по s15), но еще не достигли средней части (видно по s71 или s72)?Я также рассматриваю продолжительность;сколько времени понадобилось для перехода коробки с s15 на s71?Или, может быть, это лучше оставить для второго вопроса.Спасибо!

1 Ответ

0 голосов
/ 05 октября 2018

demo: db <> fiddle

SELECT parcel, passed_scanners
FROM (
    SELECT
        parcel,
        array_agg(scanner) as passed_scanners
    FROM
        scanners
    GROUP BY parcel
)s
WHERE 's15' = ANY(passed_scanners) AND NOT (ARRAY['s71', 's72'] && passed_scanners)
  1. Объединение всех пройденных scanner_id s для каждой посылки
  2. Фильтрация всех строк участков, содержащих #15 в passed_scanners, но ни # 71, ни # 72 (оператор && для двух массивов проверяет, содержатся ли элементы массива в обоих массивах - так называемое перекрытие массива )

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

SELECT parcel, duration
FROM (
    SELECT
        parcel,
        MAX(time) FILTER (WHERE scanner IN ('s71', 's72')) -
        MIN(time) FILTER (WHERE scanner = 's15') AS duration,
        array_agg(scanner) as passed_scanners
    FROM
        scanners
    GROUP BY parcel
)s
WHERE 's15' = ANY(passed_scanners) AND (ARRAY['s71', 's72'] && passed_scanners)
  1. Снова агрегируйте все переданные scanner_ids для каждой посылки
  2. Выдайте первый раз длясканер 15 и последний раз для сканера 71 или 72. Постройте разницу, чтобы получить длительность.
  3. Отфильтруйте все строки участков, содержащие # 15 в passed_scanners и либо # 71, либо # 72

Обратите внимание : Без какого-либо компонента даты в столбце time результат для продолжительности может не работать, если посылка сканируется за полночь.Тогда ваш старт на s15 может быть в 23 часа, а пункт назначения - в 1 час.Разница во времени будет (1 - 23) = -22.Чтобы решить эту проблему, я настоятельно рекомендую сохранить всю метку времени с частью даты.

В противном случае вам нужно проверить: Если duration < 0, то добавьте 24 часа (но что, если посылке требуется больше, чем 24 часа? Как узнатьчто вам не нужно добавлять 48 часов?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...