繁体   English   中英

X的关注者,在单个JOIN查询中排除Y的关注者(多对多通过)

[英]followers of X, excluding followers of Y in single JOIN query (many-to-many through)

我的问题的答案很可能是“那是你能做的最好的事情”,但我希望我只是看着这个太久而且缺少一些东西......

参考关于非对称关系的这篇文章 ,我正在研究“共同的朋友关系”查询。 以下是文章中的模型:

class Person(models.Model):
    name = models.CharField(max_length=100)
    relationships = models.ManyToManyField('self', through='Relationship', 
                                           symmetrical=False, 
                                           related_name='related_to')

    def get_friends(self):
        return self.relationships.filter(
            to_people__from_person=self,
            from_people__to_person=self)

class Relationship(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_people')
    to_person = models.ForeignKey(Person, related_name='to_people')

get_friends()导致JOIN查询。

我想要做的查询是“人们关注person_A但不关注person_B”。 多对多的关系删除了大量的工作,只留下了一个简单的查询要求...所以我有这个:

person_A.relationships\
    .filter(from_people__to_person=person_A)\
    .exclude(from_people__to_person=person_B)

结果包含一个子查询:

SELECT `person`.`id` FROM `person` 
INNER JOIN `relationship` ON (`person`.`id` = `relationship`.`to_person_id`) 
INNER JOIN `relationship` T4 ON (`person`.`id` = T4.`from_person_id`) 
WHERE (
    `relationship`.`from_person_id` = 178  
    AND T4.`to_person_id` = 178  
    AND NOT (`person`.`id` IN (
        SELECT U1.`from_person_id` FROM `relationship` U1 
        WHERE (U1.`to_person_id` = 191  AND U1.`from_person_id` IS NOT NULL)
    ))
)

这种排除查询是否意味着需要子查询,或者我只是缺少一些简单的调整?

假设你的表(可能是简化的)看起来像是这样的:

人:

id   |   name
-------------
1    |   Zane
2    |   Jeff
3    |   Troy
5    |   Steffan
6    |   Lolo
7    |   Katrina

关系:

from_id   |   to_id
-------------------
1         |   5
1         |   6
2         |   5
2         |   1
2         |   5
3         |   1
5         |   1
5         |   2
7         |   5

from_id是跟随to_id ,和一个人不能按照他或她的自我。

我们希望得到5不是1追随者的所有粉丝,我们希望得到这样的结果:

id   |   name
--------------
1    |   Zane
7    |   Katrina

您可以使用此解决方案:

SELECT    a.id, a.name
FROM      person a
JOIN      relationship b ON a.id = b.from_id
LEFT JOIN (
          SELECT from_id
          FROM   relationship
          WHERE  to_id = 1
          ) c ON b.from_id = c.from_id
WHERE     b.to_id = 5 AND
          c.from_id IS NULL

SQLFiddle演示

暂无
暂无

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

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