rawsql等价的django查询集

h6my8fg2  于 2021-06-17  发布在  Mysql
关注(0)|答案(2)|浏览(384)

我想写django queryset,它相当于下面的查询,在db中只命中一次。现在我正在使用 manager.raw() 执行。
annotate ,我可以生成内部查询。但是我不能在过滤条件下使用它(当我检查时) queryset.query ,看起来像ex1)。

select *
from table1
where (company_id, year) in (select company_id, max(year) year
                             from table1
                             where company_id=3
                             and total_employees is not null
                             group by company_id);

例1:

SELECT `table1`.`company_id`, `table1`.`total_employees`
FROM `table1`
WHERE `table1`.`id` = (SELECT U0.`company_id` AS Col1, MAX(U0.`year`) AS `year`
                       FROM `table1` U0
                       WHERE NOT (U0.`total_employees` IS NULL)
                       GROUP BY U0.`company_id`
                       ORDER BY NULL)

型号:

class Table1(models.Model):
    year = models.IntegerField(null=False, validators=[validate_not_null])
    total_employees = models.FloatField(null=True, blank=True)
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='dummy_relation')
    last_modified = models.DateTimeField(auto_now=True)
    updated_by = models.CharField(max_length=100, null=False, default="research")

    class Meta:
        unique_together = ('company', 'year',)

我很感激你的回答。

bvjveswy

bvjveswy1#

如果您有型号名称是 Table1 ,试试这个。

Table1.objects.get(pk=Table1.objects.filter(company_id=3, total_employees_isnull=False).latest('year').first().id)

这可能是db中的一个。
但如果 .first() 什么都不匹配。最好这样:

filter_item = Table1.objects.filter(company_id=3, total_employees_isnull=False).latest('year').first()
if filter_item:
   return Table1.objects.get(pk=filter_item.id)
0lvr5msh

0lvr5msh2#

您可以使用outerref和subquery来实现它。试着这样做:

newest = Table1.objects.filter(company=OuterRef('pk'), total_employees_isnull=False).order_by('-year')
companies = Company.objects.annotate(total_employees=Subquery(newest.values('total_employees')[:1])).annotate(max_year=Subquery(newest.values('year')[:1]))

# these queries will not execute until you call companies. So DB gets hit once

显示值:


# all values

companies.values('id', 'total_employees', 'max_year')

# company three values

company_three_values = companies.filter(id=3).values('id', 'total_employees', 'max_year')

按最大年份筛选:

companies_max = companies.filter(max_year__gte=2018)

仅供参考: OuterRef 以及 Subquery 在django版本1.11中提供

相关问题