在 sqlalchemy 中使用嵌套查询或子查询进行复杂连接 - 找到最接近的日期匹配

Complex join with nested or subqueries in sqlalchemy - find the closest date match

我们有 2 个 table 包含 global_id 加入。我们称它们为 device_updatesclient_updates。他们各自的 tables(虽然减少以帮助解决问题)如下所示:

device_updates

update_id global_id 已创建 device_date
整数 整数 日期时间 日期时间

client_updates

客户端_update_id global_id 已更新 updated_by update_type
整数 整数 日期时间 整数 字符串

*请注意,真正的 table 有一个代表 update_type 的整数。这只是为了清楚起见。

当设备改变状态时,它总是更新 device_updates table。如果这是警报状态,则客户端会收到通知并可以选择 'update' 将警报静音(作为示例)。

我们需要做的是按时间顺序从设备更新和客户端更新中生成所有事件的历史记录。但是由于 table 都不知道彼此(global_id 除外),我无法弄清楚如何确保每个返回的行都包含当时的确切状态。此外,由于每秒可能有几千台设备更新,并且客户端只需单击一下即可使所有设备静音,因此我们无法在客户端更新 table 中添加引用设备的列 table 行,因为它都很慢,我们还计划进行批量上传以满足速度要求,这意味着我们无法分配匹配的 ID。

例如流程:

  1. 具有 global_id 15 次状态更改的设备
  2. 客户端 7 更新它以使其在几秒钟后静音
  3. global_id15 的设备在未来某个时间再次改变状态

'event_history' 查询应返回的内容如下:

update_id global_id 已创建 device_date 客户端_update_id 已更新 updated_by update_type
1 15 10:53:24 10:53:23
2 15 10:53:24 10:53:23 1 10:53:34 7 “沉默”
3 15 10:57:09 10:57:8

总而言之,我如何将 device_updates table 加入 client_updates table,但请注意,设备更新不一定具有关联的客户端更新,但所有客户端更新都需要找到与更新时间匹配的确切设备更新(请注意,更新总是发生在之后 device_date)。另请注意,可能有数千台设备,因此它不仅仅是针对单个 global_id.

更新 我忘记添加我尝试过的查询示例,如下所示:

db.query(
  client_updates,
  device_updates
).outerjoin(
  device_updates, device_updates.device_update_id==db.query(
    device_updates
  ).filter(
    device_updates.global_id==client_updates.global_id,
    device_updates.device_date<client_updates.updated
  ).order_by(
    device_updates.updated.desc()
  ).first().device_update_id
)

但这似乎找到了相同的 device_update_id 来匹配所有内容。

一个临时解决方案是确保在输入时有一个id链接两个table中的每一行。这并不难,因为传入的数据确实可以访问唯一 ID。如果数据通过设备更新并需要更新 client_updates table,它会使用此 ID。当客户端更新它时,他们已获得该 ID,因此他们的静音请求也可以包括该 ID。 仅具有单个历史记录 table 也可能很有用,即 'every data',这将确保快速查找。 最好的选择是正确考虑使用 Kafka 来处理所有这些。

最终选择了 Kafka 解决方案。超快速的结果,因为我的测试构建能够轻松处理非常高的吞吐量,我现在对它的稳健性和快速性充满信心。