我真的不知道如何将GROUP BY
和HAVING
翻译成Django的QuerySet.annotate
和QuerySet.aggregate
。我正在尝试将此SQL查询转换为ORM发言
SELECT EXTRACT(year FROM pub_date) as year, EXTRACT(month from pub_date) as month, COUNT(*) as article_count FROM articles_article GROUP BY year,month;
输出:
[(2008.0, 10.0, 1L), # year, month, number of articles
(2009.0, 2.0, 1L),
(2009.0, 7.0, 1L),
(2008.0, 5.0, 3L),
(2008.0, 9.0, 1L),
(2008.0, 7.0, 1L),
(2009.0, 5.0, 1L),
(2008.0, 8.0, 1L),
(2009.0, 12.0, 2L),
(2009.0, 3.0, 1L),
(2007.0, 12.0, 1L),
(2008.0, 6.0, 1L),
(2009.0, 4.0, 2L),
(2008.0, 3.0, 1L)]
我的Django模型:
class Article(models.Model):
title = models.CharField(max_length=150, verbose_name=_("title"))
# ... more
pub_date = models.DateTimeField(verbose_name=_('publishing date'))
这个项目应该在几个不同的数据库系统上运行,所以我试图尽可能远离纯SQL。
答案 0 :(得分:14)
我认为要在一个查询中执行此操作,您可能需要将月份和年份作为单独的字段...
Article.objects.values('pub_date').annotate(article_count=Count('title'))
pub_date会group by
。但我无法想到在那里内联extract
函数子句。
如果你的模特是:
class Article(models.Model):
title = models.CharField(max_length=150, verbose_name=_("title"))
# ... more
pub_date = models.DateTimeField(verbose_name=_('publishing date'))
pub_year = models.IntegerField()
pub_month = models.IntegerField()
然后你可以这样做:
Article.objects.values('pub_year', 'pub_month').annotate(article_count=Count('title'))
如果您要执行此操作,我建议您通过覆盖文章的pub_year
方法并从pub_month
中提取值来自动填充save()
和pub_date
修改强>
一种方法是使用extra;但它不会授予您数据库独立性......
models.Issue.objects.extra(select={'year': "EXTRACT(year FROM pub_date)", 'month': "EXTRACT(month from pub_date)"}).values('year', 'month').annotate(Count('title'))
虽然这可行,但我认为(未经测试),如果您更改数据库服务器,则需要修改extra
字段。例如,在SQL Server中,您将执行year(pub_date)
而不是extract(year from pub_date)
...
如果您想出一个自定义模型管理器,并且需要进行此类数据库引擎相关更改,那么这可能并不是那么糟糕。
答案 1 :(得分:2)