【问题标题】:get list of items at a location from a table of arrivals从到达表中获取某个位置的项目列表
【发布时间】:2016-02-27 00:39:34
【问题描述】:

假设我有一个表格“arrivals”,它记录了物品到达某个位置的时间。每行对应一个到达事件。

arrivals
========
LocationId     ItemId     TimeStamp
------------------------------------------
a              1          2015-11-24 11:00  (item 1 arrived at 11:00 at location a)
a              2          2015-11-24 11:01  (item 2 arrived at 11:00 at location a)
b              1          2015-11-24 11:05  (item 1 left location a and arrived at b)
b              2          2015-11-24 11:06  (item 2 left location a and arrived at b)

是否有一条 SQL 语句可以告诉我 11:03 在位置 A 哪些项目在哪里,可能不会让 SQL 服务器崩溃?

(这将包括在 11:03 之前到达位置 A 并且此后未到达其他任何地方的所有物品)

每个地点通常同时有大约 30 件物品,100 个不同地点,每个地点每小时大约有 1000 人次到达。

是否有任何设计选择可以简化此类查询,即使这意味着对数据库进行非规范化?

目前我什至无法想象一个 sql 命令可以让我获得这些信息,而无需在自定义循环中遍历整个表。

【问题讨论】:

  • 所以物品在位置之间以光速移动?因为我没有看到任何表明物品是从位置 A 发货的
  • 位置彼此相邻,例如位置“conveyor_1”直接通向位置“conveyor_2”,中间没有空格。

标签: sql database select database-design sql-server-2012


【解决方案1】:

我使用DISTINCT 以防一件物品可以到达一个位置并返回

'2015-11-24 11:03'之前检查location A上的每个项目 但在'2015-11-24 11:03'之后的任何其他位置都不存在

SELECT DISTINCT  ItemId     
FROM arrivals lA   -- location A
WHERE LocationId = 'A'
  AND lA.TimeStamp < '2015-11-24 11:03'
  AND NOT EXISTS (SELECT 1
                  FROM arrivals lX -- any other location
                  WHERE lX.LocationId <> lA.LocationId     
                    AND lX.ItemId = lA.ItemId     
                    AND lX.TimeStamp >= '2015-11-24 11:03'
                 )

注意:您可能需要仔细检查&lt;&gt;= 以满足您的需要

【讨论】:

  • 这看起来很有希望,但我担心性能。每个位置每小时 1000 件商品,到达表仅在 10 天后就会有数百万条条目;这看起来需要对每个查询进行多次扫描。
  • 对于LocationIdItemIdTimeStamp,您需要CREATE INDEX,并且可能需要包含所有三个字段的复合索引。 EXISTS 非常高效,如果发现使用复合索引的内容将返回 false 并继续。
  • 首先创建单个索引。检查执行PLAN stackoverflow.com/questions/7359702/… 然后添加复合索引,再次检查PLAN。
  • 我认为不需要它。但是,如果您仍然想提高性能并且可以添加一些其他限制,例如一项不能在一个位置超过一天,您可以使用lA.TimeStamp between '2015-11-23 11:03' AND '2015-11-24 11:03' 来减少要比较的行数
【解决方案2】:

如果您想了解在给定时间或更早到达该位置的所有物品,这应该可以解决问题:

SELECT distinct ItemId FROM arrivals WHERE LocationId = 'a' AND TimeStamp <= '2015-11-24 11:03'

编辑: 并考虑到这样一个事实,即某些东西可能在它到达之后仍然在我们的时间戳之前离开了该位置,我建议这样做:

SELECT arrivals_prim.itemId FROM
    (SELECT itemId, max("TimeStamp") as last_arrival
        FROM arrivals
        WEHRE 
            "TimeStamp" <= '2015-11-24 11:03' 
            and locationId = 'a'
        GROUP BY itemId) arrivals_prim
    LEFT JOIN (SELECT itemId, max("TimeStamp") as last_departure
        FROM arrivals
        WEHRE
            "TimeStamp" < '2015-11-24 11:03'
            and locationId <> 'a'
        GROUP BY itemId) arrivals_bis
    ON (arrivals_prim.itemId = arrivals_bis.itemId)
    WEHRE last_departure is null or last_departure < last_arrival

【讨论】:

  • 如果 item1 在 10:00 在 loc A 但在 11:00 在 loc B 怎么办?
  • @JuanCarlosOropeza 是正确的,这将计算已经离开该位置的项目。
  • 哦,没想到。如果有另一列包含“出发”日期会很容易,但我会想一些在没有日期的情况下可行的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 2018-09-21
  • 1970-01-01
  • 2010-09-26
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多