【问题标题】:How to get table alias for inner join in django如何在 django 中获取内部连接的表别名
【发布时间】:2019-07-29 22:55:45
【问题描述】:

我使用 django 2.1、python 3.6 和 SQL Server 2012 作为后端。我有以下型号:

class ModelA(models.Model):
    name = models.CharField(...)
    value = models.PositiveIntegerField(...)

class ModelB(models.Model):
    name = models.CharField(...)
    values = models.ManyToManyField(ModelA, through='ModelC')

class ModelC(models.Model):
    model_a = models.ForeignKey(ModelA, ...)
    model_b = models.ForeignKey(ModelB, ...)
    info_a = models.CharField(...)
    info_b = models.CharField(...)

如何实现以下 SQL 查询:

SELECT t1.model_a_id AS a_id, t3.value AS a_value
FROM ModelB AS t0
INNER JOIN ModelC t1 ON t1.model_b_id = t0.id
INNER JOIN ModelC t2 ON t2.model_b_id = t0.id
INNER JOIN ModelA t3 ON t3.id = t2.model_a_id
INNER JOIN ModelC t4 ON t4.model_b_id = t0.id
WHERE t1.model_a_id in (1,2) AND t2.model_a_id in (8,9,10,11) AND t4.model_a_id in (21,22)

到目前为止我所拥有的:

ModelB.objects.filter(values__in=[1,2]).filter(values__in=[8,9,10,11]).filter(values__in=[21,22])

这会产生正确的过滤查询集。但是我怎样才能得到正确的字段呢?

我尝试使用annotate 函数但失败了。如文档中所述使用 django 的 Subquery 会生成数据库错误,因为 SQL Server 不支持 SELECT 部分中的子查询。

有什么建议吗?谢谢!

【问题讨论】:

    标签: python django django-filter django-annotate django-subquery


    【解决方案1】:

    我解决了它而没有退回到原始 sql。我将 django 的 FilteredRealtion 对象与其他 annotate 结合使用,如下所示:

    from django.db.models import Q, F, FilteredRelation
    
    qs = ModelB.objects.filter(values__in=[21,22])
    qs = qs.filter(values__in=[1,2])
    qs = qs.filter(values__in=[8,9,10,11])
    qs = qs.annotate(_a_id=FilteredRelation('modelc', condition=Q(values__in=[8,9,10,11])),
                     _a_value=FilteredRelation('modelc', condition=Q(values__in=[1,2])))
    qs = qs.annotate(a_id=F('_a_id__model_a'), a_value=F('_a_value__model_a__value'))
    qs = qs.values('a_id', 'a_value')
    

    【讨论】:

      【解决方案2】:

      您的查询不是最佳的,但这是一个不同的问题。 你可以试试raw query

      所以你可以运行:

      query = """
      SELECT t1.model_a_id AS a_id, t3.value AS a_value
      FROM ModelB AS t0
      INNER JOIN ModelC t1 ON t1.model_b_id = t0.id
      INNER JOIN ModelC t2 ON t2.model_b_id = t0.id
      INNER JOIN ModelA t3 ON t3.id = t2.model_a_id
      INNER JOIN ModelC t4 ON t4.model_b_id = t0.id
      WHERE t1.model_a_id in ({0}) AND t2.model_a_id in ({1}) AND t4.model_a_id in 
      ({2})"""
      t1_filters = ','.join(['1','2'])
      t2_filters = ','.join(['8', '9', '10', '11'])
      t4_filters = ','.join(['21', '22'])
      
      results = ModelA.objects.raw(query.format(t1_filters, t2_filters, t4_filters))
      for instance in results.all():
          print(instance)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-16
        • 1970-01-01
        • 1970-01-01
        • 2014-07-07
        • 1970-01-01
        • 2021-12-28
        • 1970-01-01
        相关资源
        最近更新 更多