Self join in Django



对以下表执行自连接查询:

> select * from test_users
id  email
--- -----------
1   "a@abc.com"
2   "a@abc.com"
3   "b@abc.com"
我可以使用SQL:
> select u1.id u1id, u2.id u2id from test_users u1 inner join test_users u2 on u1.email=u2.email and u1.id !=u2.id
u1id   u2id
-----  ------
1      2
2      1

问题:

  1. 我如何在Django ORM中写这个?
  2. 如果我想删除重复,以便在上面的例子中我只得到1行,我如何在Django中实现?

可以通过Exists检索主键大于(或小于)用户主键的Users。子查询(Django-doc):

from django.db.models import Exists, OuterRef
Users.objects.filter(
Exists(
User.objects.filter(
pk__gt=OuterRef('pk'),
email=OuterRef('email')
)
)
)

如果在这些对象上调用.delete(),则将删除所有存在另一个Users对象且具有更大主键的User

在django-3.0之前,应该将Exists子查询移动到.annotate(…)子句,然后在此进行过滤:

from django.db.models import Exists, OuterRef
Users.objects.annotate(
has_other=Exists(
User.objects.filter(
pk__gt=OuterRef('pk'),
email=OuterRef('email')
)
)
).filter(has_other=True)