【问题标题】:Select first object of group by in postgresql/sqlalchemy在 postgresql/sqlalchemy 中选择 group by 的第一个对象
【发布时间】:2017-09-02 11:18:33
【问题描述】:

我在 sqlachemy 中有一个使用 SQLite 的请求,它返回 group by 的一个对象和一个值(avg):

result = session.query(
        obj, func.avg(obj.value).label("value_avg")
    ).group_by(
        func.strftime('%s', obj.date)
    ).all()

但现在我需要使用限制性更强的 postgresql(严格的 SQL),我需要做同样的事情,但它需要用 func.avg() 之类的组中的某些东西替换 query(obj) 或其他东西.所以我想知道是否存在任何能够返回每个组的第一个 obj 的函数。如果不可能,也许我可以为我的 obj 实现比较器,例如像这样调用 func.min(obj) :

result = session.query(
        func.min(obj), func.avg(obj.value).label("value_avg")
    ).group_by(
        func.date_part('second', obj.date)
    ).all()

也许在我的 obj 模型中实现 cmpeq ? (最佳做法是什么)

编辑:

我有一个解决方法,但我不确定这是一个好习惯。第一个分组和下一个加入:

sq = session.query(
        func.min(obj.date).label("date"), func.avg(obj.value).label("value_avg")
    ).group_by(
        func.cast(func.extract('second', obj.date) / 600, Integer)
    ).order_by(obj.date).subquery()
result = session.query(obj, sq.c.value_avg).join(sq,sq.c.date == obj.date).all()

我想要的是每个组的第一个 obj 和组的 value_avg

【问题讨论】:

  • 您的解决方案(通常)可能会返回多个结果。除非min() 中的值是唯一的(我猜它是唯一的,因为id 听起来像一个主键;但如果它只是一个外键,那可能不是这种情况)。 -- 这是greatest-n-per-group 的特例(其中N=1)。 SO上已经有很多SQL解决方案了,但我不知道哪个最适合SQLAlchemy
  • 对不起,我将 ID 编辑为日期,而日期是唯一的索引。
  • 但这没有多大意义,因为SELECT min(date) ... GROUP BY dateSELECT date ... GROUP BY date 是相同的(无论如何date 组中只有一个date)。 -- 另外,单个索引并不能保证其唯一性。
  • 是的,我同意,但在我的结果中,我可以访问我需要的其他属性。使用 SQlite 我没有这个问题,因为在第一种情况下你可以这样做,因为 query(obj, func.avg(obj.value).label("value_avg")) 让我可以访问 obj 属性
  • 如果您需要同时选择聚合值和非聚合值,为什么不使用over()

标签: python postgresql sqlite sqlalchemy


【解决方案1】:

您需要列出所有要选择的列并将它们放在 group_by 中。然后,您可以选择不属于 group by 的聚合列。

result = session.query(
    obj.column1,
    obj.column2,
    obj.column3,
    func.strftime('%s', obj.date),
    func.avg(obj.value).label("value_avg")
).group_by(
    obj.column1,
    obj.column2,
    obj.column3,
    obj.date
).all()

【讨论】:

  • 是的,但是当你必须用惰性查询处理像 obj.obj2.obj3 这样的外来对象时并不容易
猜你喜欢
  • 2013-01-26
  • 2014-11-22
  • 2021-07-14
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多