在 SqlAlchemy 上使用 distinct on (Postgres) 的正确方法是什么?

Shu*_*ham 5 python postgresql sqlalchemy flask-sqlalchemy

我想使用 max(timestamp) 获取表的所有列并按名称分组。

到目前为止我尝试过的是: normal_query ="Select max(timestamp) as time from table"

event_list = normal_query \
            .distinct(Table.name)\
            .filter_by(**filter_by_query) \
            .filter(*queries) \
            .group_by(*group_by_fields) \
            .order_by('').all()
Run Code Online (Sandbox Code Playgroud)

我得到的查询:

SELECT  DISTINCT ON (schema.table.name) , max(timestamp)....
Run Code Online (Sandbox Code Playgroud)

此查询基本上返回带有名称和时间戳的两列。

而我想要的查询:

SELECT DISTINCT ON (schema.table.name) * from table order by ....
Run Code Online (Sandbox Code Playgroud)

它返回该表中的所有列。这是预期的行为,我能够获取所有列,我怎么能在 python 中将其正确处理以获取此语句?.基本上星号丢失了。有人可以帮助我吗?

Ilj*_*ilä 7

您似乎在追求的是DISTINCT ON ... ORDER BYPostgresql 中用于选择结果(N = 1)的习惯用法。所以,而不是分组和聚合只是

event_list = Table.query.\
    distinct(Table.name).\
    filter_by(**filter_by_query).\
    filter(*queries).\
    order_by(Table.name, Table.timestamp.desc()).\
    all()
Run Code Online (Sandbox Code Playgroud)

这将最终选择按名称“分组”的行,具有最大的时间戳值。

大多数时候您不想使用星号,无论如何也不想在您的应用程序代码中使用星号,除非您正在执行手动即席查询。星号基本上是“FROM表/关系中的所有列”,如果您添加列,对它们重新排序等,这可能会在以后破坏您的假设。

如果您想根据最终结果中的时间戳对结果行进行排序,您可以使用例如Query.from_self()将查询转换为子查询,并在封闭查询中排序:

event_list = Table.query.\
    distinct(Table.name).\
    filter_by(**filter_by_query).\
    filter(*queries).\
    order_by(Table.name, Table.timestamp.desc()).\
    from_self().\
    order_by(Table.timestamp.desc()).\
    all()
Run Code Online (Sandbox Code Playgroud)