【问题标题】:Django Subquery with Scalar Value带有标量值的 Django 子查询
【发布时间】:2016-06-24 20:58:46
【问题描述】:

是否可以使用 Django ORM 将子查询结果与标量值进行比较?我很难转换这个:

SELECT payment_subscription.*
FROM payment_subscription payment_subscription
  JOIN payment_recurrent payment_recurrent ON payment_subscription.id = payment_recurrent.subscription_id
WHERE
  payment_subscription.status = 1
  AND (SELECT expiration_date
       FROM payment_transaction payment_transaction
       WHERE payment_transaction.company_id = payment_subscription.company_id
             AND payment_transaction.status IN ('OK', 'Complete')
       ORDER BY payment_transaction.expiration_date DESC, payment_transaction.id DESC
       LIMIT 1) <= ?

主要有以下几点:

  1. 子查询的标量值与任意参数的最后一次比较。
  2. 子查询和带有公司ID的外部查询之间的连接

【问题讨论】:

    标签: python mysql django database


    【解决方案1】:

    您可以(从 Django 1.11 开始)对子查询进行注释,并对其进行切片以确保您只获得“第一个”结果。然后,您可以通过与您想要的值进行比较来过滤该子查询注释。

    from django.db.models.expressions import Subquery, OuterRef
    
    expiration_date = Transaction.objects.filter(
        company=OuterRef('company'),
        status__in=['OK', 'Complete'],
    ).order_by('-expiration_date').values('expiration_date')[:1]
    
    Subscription.objects.filter(status=1).annotate(
        expiration_date=Subquery(expiration_date),
    ).filter(expiration_date__lte=THE_DATE)
    

    不过……

    目前这可能会导致性能非常差:您的数据库将对子查询进行两次评估(一次在 where 子句中,来自过滤器,再次在 select 子句中,来自注释)。正在努力解决此问题,但目前尚未完成。

    【讨论】:

      【解决方案2】:
      Subscription.objects.annotate(
          max_expiraton_date=Max('transaction__expiration_date')
      ).filter(
          status=1,
          recurrent__isnull=False,  # [inner] join with recurrent
          transaction__status__in=['OK', 'Complete'],
          max_expiraton_date=date_value
      )
      

      这会产生其他 SQL 查询,但会获得相同的 Subscription 对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-16
        • 1970-01-01
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多