使用Postgres灌注自动化日志

时间:2018-10-05 20:35:32

标签: postgresql

我想不出一个很好的标题。我有一个自动化仓库,里面有输送机移动箱子。每个盒子都有一个唯一的包裹编号。有数十个扫描仪告诉盒子要去的地方。扫描仪每次看到一个框时,都会在表中创建两行(排序和确认),如下所示:

    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 :(得分:1)

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
  2. 过滤所有{{1}中包含#15但不包含#71或#72(passed_scanners两个数组的运算符)的地块行,检查两个数组是否都包含数组元素-称为 array overlay

第二部分是一个不同的查询,因为在第一部分中,您要求仍未到达最终扫描仪的包裹。在第二部分中,您要计算最终到达s71的所有包裹的持续时间。

&&
  1. 再次汇总每个包裹的所有通过的scanner_ids
  2. 给出扫描仪15的第一时间,给出扫描仪71或72的最后时间。建立差异以获取持续时间。
  3. 过滤所有包含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) 中的#15以及#71或#72的地块行

请注意:如果您的包裹在午夜扫描,passed_scanners列中没有任何日期成分,则持续时间的结果可能不起作用。然后,您可能会在s15开始于23h,而目的地将在1h。时差为time。为了解决这个问题,我强烈建议您保存带有日期部分的整个时间戳。

否则,您必须检查:如果(1 - 23) = -22然后增加24小时(但是如果包裹需要超过24小时又该怎么办?如何知道您不需要增加48小时呢?)