首页 > 解决方案 > 如何在按属性分组时查询对象集合

问题描述

因此,我正在尝试编写一个查询,该查询将选择在某个属性上不同的对象集合。

行动:

+-----+-----------+-----+
| id  | timestamp | ... |
+-----+-----------+-----+
|  10 | 16:04     | ... |
|  11 | 16:06     | ... |
|  12 | 16:08     | ... |
|  13 | 16:09     | ... |
|  14 | 16:10     | ... |
+-----+-----------+-----+

版本:

+----+--------+-----------+-------------------+
| id | foo_id | action_id | foo_zab           |
+----+--------+-----------+-------------------+
|  1 |      1 |        10 | xx                |
|  2 |      2 |        11 | yy                |
|  3 |      3 |        12 | zz                |
|  4 |      3 |        13 | zy                |
|  5 |      3 |        14 | zx                |
+----+--------+-----------+-------------------+

福:

+----+-----+
| id | zab |
+----+-----+
|  1 | xx  |
|  2 | yy  |
|  3 | zx  |
+----+-----+

一个场景是由一组 foo 组成的。我正在尝试跟踪每个特定 foo 随着时间的变化。因此,每次对 foo 进行更改时,都会记录导致该更改的操作,并将 foo 的一些属性的副本存储在foo_versions表中

我正在寻找的是“特定动作中的 foos 状态”。因此,虽然动作 #11 仅专门链接到 foo,但动作 #11 的场景状态实际上包含 3 个 foo,其版本是 foo_version #1、#2 和 #5

我需要构建一个查询,它会说“对于指定的动作,给我场景的表示”

对于动作 #10,场景将是[<foo_version #1>]

对于动作 #12,场景将是[<foo_version #1>, <foo_version #2>, <foo_version #3>]

这就是棘手的地方。对于动作 #14,场景的表示是[<foo_version #1>, <foo_version #2>, <foo_version #5>]。Foo 版本 #3、#4 和 #5 都引用相同的 foo。因此,foo 版本 #3 和 #4 被 #5 覆盖。

我正在使用这个 sqlalchemy 查询:

stmt = db.session.query(Action).filter(Action.timestamp <= action.timestamp).subquery()
action_alias = aliased(Action, stmt)

foo_versions = db.session.query(FooVersion) \
                         .join(Action) \
                         .join(action_alias, FooVersion.action) \
                         .filter(Action.frame_id == frame.id) \
                         .all()

我得到的结果是

[<foo_version #1>, <foo_version #2>, <foo_version #3>, <foo_version #4>, <foo_version #5>]]]
                                     |____________|    |____________|
                                           ^                 ^
                                           |                 |
I need to get rid of these versions     -> |                 |
since they have been overwritten 

标签: pythonmysqlormsqlalchemy

解决方案


我对 python 不熟悉,但如果我正确地得到了你想要的,这里是 SQL 查询:

SELECT a.id as action_id, timestamp, 
v.id as version, foo_id, foo_zab
FROM action a
JOIN foo_version v 
ON ( v.action_id IN
  ( 
    SELECT MAX(inner_v.action_id)
    FROM foo_version inner_v 
    WHERE a.id >= inner_v.action_id
    GROUP BY inner_v.foo_id
  )                      
)
JOIN foo ON ( foo.id = v.foo_id ) 
ORDER BY a.id, version

它将为您提供与每个版本的数据重复的每个操作行,这是一个SQL fiddle 演示


推荐阅读