【问题标题】:How to select latest objects using max(date) with SQLAlchemy如何使用 max(date) 和 SQLAlchemy 选择最新的对象
【发布时间】:2020-10-13 07:25:17
【问题描述】:

正如我在回答中提到的,这是错误的方法。

我的声明:

db.session.query(
  m.SiteServicePrice, func.max(m.SiteServicePrice.created).label('latest')).filter(
    m.SiteServicePrice.site_id == 2001).group_by(m.SiteServicePrice.service_id).all()

我想取回 m.SiteServicePrice 对象列表,而不是元组列表。

这个:

[<SiteServicePrice(site_id:2001 service_id:12 created:2019-01-30 03:25:31)>,
 <SiteServicePrice(site_id:2001 service_id:21 created:2019-01-30 03:25:31)>,
 <SiteServicePrice(site_id:2001 service_id:37 created:2019-01-30 03:25:31)>] 

而不是这个:

[(<SiteServicePrice(site_id:2001 service_id:12 created:2019-01-30 03:25:31)>, datetime.datetime(2020, 5, 28, 22, 31, 35)),
 (<SiteServicePrice(site_id:2001 service_id:21 created:2019-01-30 03:25:31)>, datetime.datetime(2020, 5, 28, 22, 31, 54)),
 (<SiteServicePrice(site_id:2001 service_id:37 created:2019-01-30 03:25:31)>, datetime.datetime(2020, 5, 28, 22, 32, 15)))] 

有没有办法将func.max(m.SiteServicePrice.created) 保留为查询的一部分,并指示 SQLAlchemy 不要将其包含在结果中?

我知道我可以使用列表推导或其他方式从结果中提取 m.SiteServicePrice 对象,但我很好奇是否有办法使用 SQLAlchemy 来做到这一点。

【问题讨论】:

    标签: python sql sqlalchemy


    【解决方案1】:

    原来我原来的 SQL 查询和 SQLAlchemy 语句不正确。

    原始sql查询:

    select 
      max(created), 
      created, 
      service_id, c_price, s_price 
    from 
      site_service_prices 
    where 
      site_id = 2001 
    group by service_id;
    

    这里我没有将来自select 的所有键都包含在group by 中。 MySQL 和 MariaDB 不会将此视为错误,它确实如此。 Explanation from MariaDB knowledge-base

    要使用 max(date_field) 从查询中获取 latest 项目列表,需要子查询。

    这是正确的查询:

       1 SELECT
       2   id, site_id, service_id, created
       3 FROM
       4   site_service_prices join(
       5     SELECT
       6       site_id, service_id, max(created) AS created
       7     FROM
       8       site_service_prices
       9     WHERE
      10       site_id = 1
      11     GROUP BY
      12       site_id, service_id
      13   ) t2
      14 USING (
      15   site_id, service_id, created
      16 );
    

    这就是 SQLAlchemy 查询的样子:

     # create a subquery with IDs and max date
     sq = db.session.query(
             m.SiteServicePrice.service_id.label('service_id'),
             func.max(m.SiteServicePrice.created).label('created')).filter(
                   m.SiteServicePrice.site_id == 1).group_by(
                       m.SiteServicePrice.service_id).subquery()
     # join with subquery
     db.session.query(m.SiteServicePrice).join(sq,
         and_(m.SiteServicePrice.service_id == sq.c.service_id,
              m.SiteServicePrice.created == sq.c.created)).filter(
                  m.SiteServicePrice.site_id == 1).order_by(
                      m.SiteServicePrice.created.desc()).all()
    

    【讨论】:

      【解决方案2】:

      只需用简单的 for 循环遍历它们并保存在不同的数组中。

      【讨论】:

      • 我知道我能做到。我什至在我的问题结束时提到了它。我想知道是否有一种 sqlalchemy 方法可以做我想做的事情。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 2019-08-30
      • 2018-02-16
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 1970-01-01
      相关资源
      最近更新 更多