0

私の質問への答えは「それがあなたにできる最善のことです」かもしれませんが、これをあまりにも長く見て、何かが欠けていることを願っています....

非対称関係に関するこの記事を参照して、「相互の友人関係」クエリを見ています。記事のモデルは次のとおりです。

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)
    ))
)

この種の除外クエリは必要なサブクエリを暗示していますか、それとも簡単な調整が欠けているだけですか?

4

1 に答える 1

2

テーブル(単純化されている可能性があります)が次のように見えると仮定します。

人:

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にあり、人は自分自身をフォローすることはできません。

そして、のフォロワーではないのすべてのフォロワーを取得し51たい場合は、次の結果が必要です。

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 デモ

于 2012-08-01T03:28:33.990 に答える