如何通过 django 模型查询创建与组的左连接

Posted

技术标签:

【中文标题】如何通过 django 模型查询创建与组的左连接【英文标题】:How to create left join with group by django model query 【发布时间】:2015-05-07 18:12:39 【问题描述】:

嗨,我声明了 django 模型如下,我只想通过查询运行简单的左连接。

mysql查询

SELECT  u.name, COUNT('j.*') as num_jobs FROM `User` as u 
LEFT JOIN Job as j ON u.id = j.userId_id GROUP BY j.userId_id

上面的查询是获取每个用户的工作计数。

Django 模型

from django.db import models


class Users(models.Model):       
    name = models.CharField(max_length=60,verbose_name="Name",null=True, blank=True)
    email_id = models.CharField(max_length=60,verbose_name="Email Id",null=True, blank=True)
    phonenumber = models.CharField(max_length=20, verbose_name="Phone Number")
    class Meta:
        verbose_name_plural = "Users"
        verbose_name = "Users"
        db_table = "User"
    def __unicode__(self):
        return  str(self.phonenumber) + ": "+ str(self.name)  

class Job(models.Model):
    userId = models.ForeignKey(Users)
    title = models.CharField(max_length=128,verbose_name="Title")
    description = models.TextField(verbose_name="Description",null=True, blank=True)
    class Meta:
        verbose_name_plural = "Job"
        verbose_name = "Job"
        db_table = "Job"
    def __unicode__(self):
        return  self.title

我需要在模型中调整什么吗,请指导我!

【问题讨论】:

【参考方案1】:

试试这个

from django.db.models import Count

# import your model (Job)

Job.objects.values('userId').annotate(c=Count('userId')).values('userId__name','c')

最初的values('userId') 后跟annotate 将按userId 进行计数和分组。

输出将是这样的字典列表:

['userId__name':'John','c':20,]

用户John 有20 个相关的Job 对象。

在不相关的说明中,只要您的模型中有外键。通常最好写user 而不是userId

编写查询和访问关系时更有意义(user__name 而不是userId__name)。

更新:

如果您需要其他属性,请将它们作为参数添加到第二个 values 调用中,如下所示:

Job.objects.values('userId').annotate(c=Count('userId'))\
.values('userId__name','userId__email_id','c')

【讨论】:

感谢您提供出色的解决方案,您能帮助我如何从用户表中获取所有列而不是仅名称列 我已经更新了我的帖子来回答你的其他问题。 据我所知,您必须明确指定所需的所有属性。 答案非常有帮助,只是扩展问题是否有可能做一个 coulmn alise userId__name 看起来很奇怪我想做 name 因为我我在 api 中公开它。所以django可以让我们做类似userId__name as name的事情 有一种别名的方法,但不幸的是它没有通过这里的 cmets (***.com/a/10599077/1268926) 中描述的关系。您可以编写自己的函数来重命名所有键。 api_return = ['name':k['userId__name'] for k in v] 其中 v 是我回答中的最后一个查询。【参考方案2】:

我认为最直接的解决方案是通过以下方式获取您的用户对象:

users = User.objects.filter(<filtering-expression-here>)

获得用户后,您可以通过以下方式考虑他的工作数量:

for user in users:
    print "User '%s' has %s jobs" % (user.name, str(user.job_set.count()))

PS:此建议假设您将“用户”模型重命名为“用户”(不带 s)

编辑:我将 len(...) 更改为 .count()

【讨论】:

len 不适用于user.job_set。你需要做user.job_set.count()len(user.job_set.all())。即便如此,这种方法效率低下,因为您获取 User 对象的所有属性(使用过滤器),然后使用 user.job_set 获取所有相关作业(当您只需要计数时)。 没错,感谢您指出这一点。我同意你的表现评论。但是,以编程方式,这可能是最简单的事情。 在程序上是的,当您的数据库中有很多行和/或多列时,可伸缩性方面不太好。

以上是关于如何通过 django 模型查询创建与组的左连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在jooq查询的左连接中检查记录是不是完​​全为空

如何从访问数据库中的左连接中选择excel表 - EXCEL VBA

访问为空的左连接成员时的教义痛苦

选择中的左连接与子查询的奇怪问题

ORA-00907: 两个子查询的左连接缺少右括号

FF4中的左连接linq查询