我正在处理 MySQL (5.5) 中的一些轻微扭曲的数据。我有一个用于跟踪状态(新、活动、非活动等)和“位置”更改的表,其中位置的格式为 x.0.y,x 和 y 为正整数。
我正在尝试将位置更改移动到单独的表中,但为此我需要从表中的其他记录中恢复完整的旧位置。完整的旧位置不会存储在位置更改记录中,如下所示:
id status new_loc timestamp
-- ------ ------- ---------
5 1 -> 1 1.0.2 2012-05-21 00:00:00
5 new 1.0.1 2012-05-21 00:00:03
5 1 -> 2 2.0.1 2012-05-22 00:00:00
5 2 -> 3 3.0.1 2012-05-23 00:00:00
因此,当位置发生变化时,所记录的只是完整的新位置和旧位置的第一部分(状态消息的左侧)。但是,我可以查看以前的记录以找到完整的旧位置。
我的主要问题是那里的第二排。“新”状态意味着 ID 为 5 的对象刚刚添加到数据库中。它应该始终是表中任何 id 的第一个状态。但是,在许多情况下,“新”记录在初始更改记录之后大约三秒被插入。在本例中,添加位置为 1.0.1,然后更改为 1.0.2,然后更改为 2.0.1,然后更改为 3.0.1。(编辑:真实的例子并不是这么简单或直接,但总是有一条人类可以很容易辨别的位置“路径”。)
我在尝试编写一个同时考虑第 1 行和第 3 行的查询时遇到了问题。我不能只找到最近的记录,因为它们可能是乱序的。我不能只使用与我的状态匹配的 new_loc 来获取记录,因为可能有多个匹配项。
这是我认为可行的方法:
- 查找最近的先前位置更改(如果存在),并使用其 new_loc。
- 如果不存在先前的更改,则查找该 id 状态为“新”的记录并使用其 new_loc。
我目前有一个与这两个条件都匹配的 LEFT JOIN,但我不知道如何说“如果没有匹配条件 1,则仅在条件 2 上加入”或“更喜欢在条件 1 上加入的行”。
我只是不知道该怎么做。任何帮助表示赞赏。
编辑:我应该明确 id 是一个对象 id,显然不仅仅是这个表上的一个索引。主键是 (id, status)。