【问题标题】:many to many django sql多对多 django sql
【发布时间】:2013-03-28 08:44:30
【问题描述】:

我有一个模型用户配置文件,它与另一个名为技能的表存在多对多关系 我还有一个模型组,它与另一个名为技能的表存在多对多关系

我想进行一个查询,计算用户个人资料与每个组共有的技能数量。

我还想进行查询,以计算特定用户个人资料与其他用户个人资料共同拥有的技能数量

有人可以帮我做这件事吗? 谢谢

模型:

class UserProfile(models.Model):    
    slug = models.SlugField(max_length=200)
    user = models.ForeignKey(User, unique =True)
    skills = models.ManyToManyField(Skills,null=True, blank=True)
    courses = models.ManyToManyField(Course,null=True, blank=True)

class Group(models.Model):
    slug = models.SlugField(max_length=200)
    name = models.CharField(max_length=200)
    skills = models.ManyToManyField(Skills,null=True, blank=True)

class Skills(models.Model):
    slug = models.SlugField(max_length=200)
    name = models.CharField(max_length=200)

所以我找到了一种方法来为团体做这件事

groupRecommendation = Group.objects.extra(
select={
    'skills_count': """
     SELECT COUNT(*) FROM axiom_alto_userprofile_skills
     JOIN axiom_alto_group_skills on axiom_alto_userprofile_skills.skills_id = axiom_alto_group_skills.skills_id
     WHERE axiom_alto_group_skills.group_id= axiom_alto_group.id AND axiom_alto_userprofile_skills.userprofile_id = %d """ % profile.id,

},

).order_by('-skills_count')

但我不知道如何在用户之间进行操作

【问题讨论】:

  • 请分享模型。

标签: python sql django django-queryset


【解决方案1】:

您的第一个查询是针对特定用户个人资料计算用户与每个组共享的技能数量。在您的帖子中,您展示了一种使用子查询的方法。但是,在某些数据库中,子查询的性能比联接差得多,因此您可能有兴趣了解如何使用联接而不是子查询来获得相同的结果:

SELECT G.id, G.slug, G.name, COUNT(GS.id) AS skills_count
FROM axiom_alto_group G
INNER JOIN axiom_alto_userprofile_skills US
  ON US.userprofile_id = %s
LEFT OUTER JOIN axiom_alto_group_skills GS
  ON GS.group_id = G.id AND US.skills_id = GS.skills_id
GROUP BY G.id, G.slug, G.name
ORDER BY skills_count DESC

在 Django 中,您可以在 Group 模型上使用 raw SQL query 运行它:

Group.objects.raw(''' ... SQL as above ... ''', [profile.id])

现在应该很容易了解如何执行第二个查询。也就是说,对于特定的用户个人资料,计算用户与其他用户共享的技能数量:

SELECT U.id, U.slug, U.user, COUNT(US2.id) AS skills_count
FROM axiom_alto_userprofile U
INNER JOIN axiom_alto_userprofile_skills US1
  ON US1.userprofile_id = %s
LEFT OUTER JOIN axiom_alto_userprofile_skills US2
  ON US2.userprofile_id = U.id AND US2.skills_id = US1.id
GROUP BY U.id, U.slug, U.user
ORDER BY skills_count DESC

同样,在 Django 中,您可以使用原始 SQL 查询运行它,这次是在 UserProfile 模型上:

UserProfile.objects.raw(''' ... SQL as above ... ''', [profile.id])

【讨论】:

  • 嗨,Gareth,谢谢,但问题是,skills_count 不是唯一的子查询,我有很多子查询来获得其他计数,所以通过原始数据可能会更快,但要编写一个包含很多 INNER JOIN 的 sql ...我不知道我是否能做到,这将是一场噩梦......但你是对的,如果子查询花费太多时间,我最终可能会这样做。现在我在网站上没有那么多东西,但将来我会,所以我可能需要重新考虑并使用 raw。
【解决方案2】:
groupRecommendation = Group.objects.extra(
    select={
    'skills_count': """
     SELECT COUNT(*) FROM axiom_alto_userprofile_skills
     JOIN axiom_alto_group_skills on axiom_alto_userprofile_skills.skills_id = axiom_alto_group_skills.skills_id
     WHERE axiom_alto_group_skills.group_id= axiom_alto_group.id AND axiom_alto_userprofile_skills.userprofile_id = %d """ % profile.id,
    },
).order_by('-skills_count')

【讨论】:

    猜你喜欢
    • 2012-12-01
    • 2020-05-07
    • 2017-05-15
    • 1970-01-01
    • 2014-11-11
    • 2019-09-08
    • 2021-03-01
    • 2015-07-05
    • 2019-09-15
    相关资源
    最近更新 更多