【问题标题】:group by year, month, day in a sqlalchemy在 sqlalchemy 中按年、月、日分组
【发布时间】:2018-10-08 18:33:55
【问题描述】:

我想要

DBSession.query(Article).group_by(Article.created.month).all()

但是这个查询不能使用

如何使用 SQLAlchemy 做到这一点?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    假设你的db引擎确实支持MONTH()这样的功能,你可以试试

    import sqlalchemy as sa
    DBSession.query(Article).group_by( sa.func.year(Article.created), sa.func.month(Article.created)).all()
    

    否则你可以在 python 中分组

    from itertools import groupby
    
    def grouper( item ): 
        return item.created.year, item.created.month
    for ( (year, month), items ) in groupby( query_result, grouper ):
        for item in items:
            # do stuff
    

    【讨论】:

      【解决方案2】:

      我知道这个问题很古老,但为了任何寻找解决方案的人的利益,这是不支持像 MONTH() 这样的函数的数据库的另一种策略:

      db.session.query(sa.func.count(Article.id)).\
          group_by(sa.func.strftime("%Y-%m-%d", Article.created)).all()
      

      本质上,这是将时间戳转换为可以分组的截断字符串。

      如果您只想要最近的条目,您可以添加,例如:

          order_by(Article.created.desc()).limit(7)
      

      按照此策略,您只需省略年份和月份即可轻松创建分组,例如星期几。

      【讨论】:

      • 对于 postgres 使用 date_trunc 而不是 strftime
      • 这应该是imo接受的答案!
      【解决方案3】:

      THC4k 答案有效,但我只想补充一点,query_result 需要已经排序才能让 itertools.groupby 按您想要的方式工作。

      query_result = DBSession.query(Article).order_by(Article.created).all()
      

      这里是itertools.groupby docs中的解释:

      groupby() 的操作类似于 Unix 中的 uniq 过滤器。每次键函数的值发生变化时,它都会生成一个中断或新组(这就是为什么通常需要使用相同的键函数对数据进行排序的原因)。这种行为与 SQL 的 GROUP BY 不同,后者聚合公共元素而不管其输入顺序如何。

      【讨论】:

        猜你喜欢
        • 2016-06-24
        • 2012-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-15
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        相关资源
        最近更新 更多