简体   繁体   English

如何在Django中为内部联接获取表别名

[英]How to get table alias for inner join in django

I'm using django 2.1, python 3.6 and SQL Server 2012 as backend. 我正在使用django 2.1,python 3.6和SQL Server 2012作为后端。 I have following models: 我有以下型号:

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(...)

How can I achieve following SQL query: 如何实现以下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)

What I have so far: 到目前为止,我有:

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

Which produces the correct filtered QuerySet. 产生正确的过滤查询集。 But how can I get the correct fields? 但是,如何获得正确的字段?

I tried to use annotate function but I failed. 我尝试使用annotate功能,但失败了。 Using django's Subquery as described in the docs generates database error, because SQL Server does not support subqueries in the SELECT part. 如文档中所述使用django的Subquery产生数据库错误,因为SQL Server在SELECT部分中不支持子查询。

Any recommendations? 有什么建议吗? Thanks! 谢谢!

Your query is not optimal, but that's a different issue. 您的查询并非最佳,但这是另一个问题。 You can try raw query 您可以尝试原始查询

So you can run: 这样就可以运行:

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)

I solved it without falling back to raw sql. 我解决了它,而没有退回到原始sql。 I used django's FilteredRealtion objects in combination of additional annotate like this: 我将django的FilteredRealtion对象与其他附加annotate结合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')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM