【问题标题】:What is the correct way to use distinct on (Postgres) with SqlAlchemy?在 SqlAlchemy 上使用 distinct on (Postgres) 的正确方法是什么?
【发布时间】:2019-12-06 18:17:54
【问题描述】:

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

到目前为止,我尝试过的是: normal_query ="从表中选择 max(timestamp) 作为时间"

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

我得到的查询:

SELECT  DISTINCT ON (schema.table.name) , max(timestamp)....

这个查询基本上返回两列名称和时间戳。

然而,我想要的查询:

SELECT DISTINCT ON (schema.table.name) * from table order by ....

它返回该表中的所有列。这是预期的行为,我能够得到所有的列,我怎么能在 python 中正确地得到这个语句?。基本上没有星号。 有人可以帮帮我吗?

【问题讨论】:

  • 不完全清楚你在做什么(查询是如何让你失败的,normal_query 到底是什么等等),如果你对星号有问题,阅读一个好的 SQL教程或书籍会让你快速上手。请注意,在 SQL 中,通常可以以多种方式编写相同的查询。
  • 感谢您指出,我对可能有帮助的问题几乎没有更新。
  • 您似乎真正想要的是名称上不同的行(不一定必须分组),按时间戳降序排列。这是一个例子:stackoverflow.com/questions/44069023/…。此处为纯 SQL 中的相同示例:stackoverflow.com/questions/16914098/….

标签: python postgresql sqlalchemy flask-sqlalchemy


【解决方案1】:

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

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

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

您不希望在大多数情况下使用星号,无论如何也不希望在您的应用程序代码中使用星号,除非您正在执行手动即席查询。星号基本上是“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()

【讨论】:

  • 你去。谢谢你为我节省了很多时间。这是我所期望的。对不起,如果我花了太多精力来解释。干杯!!!!
  • 我是否也可以将 count(Table.id) 添加到同一个查询而不是单独的查询中,但如果分开如何加入?如果是这样怎么办?或者你有 SqlAlchemy 文档的链接?这正确地解释了这一点
  • 嗯,也许可以使用窗口函数,但我认为我并不完全理解这里所寻求的内容。
  • 是的,上面的查询是子查询,alert_list = table.query .filter(Table.id == subquery.c.id) .order_by(Table.timestamp.desc()) .all( ) 做的工作再次感谢:)
  • 在这种情况下,另一种选择是使用Query.from_self(),因此在调用all() 之前,您需要添加...from_self().order_by(Table.timestamp.desc()).all()。 “From self”自动将原始查询转换为子查询并为(主)实体起别名。那也可以避免加入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 2021-01-08
  • 2012-05-14
相关资源
最近更新 更多