自己加入 Django
Self join in Django
要对以下 table 使用自联接执行查询:
> 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
问题:
- 如何在 Django ORM 中编写此代码?
- 如果我想删除重复项以便在上面的示例中只得到 1 行,我如何在 Django 中实现它?
您可以检索 User
s,其中有另一个项目的主键大于(或小于)具有 Exists
subquery [Django-doc] 的用户的主键:
from django.db.models import Exists, OuterRef
Users.objects.filter(
Exists(
User.objects.filter(
<strong>pk__gt=OuterRef('pk')</strong>,
<strong>email=OuterRef('email')</strong>
)
)
)
如果您因此对这些调用 .delete()
,您将删除所有 User
,因为存在另一个具有更大主键的 Users
对象。
在 django-3.0 之前,应该将 Exists
子查询移动到 .annotate(…)
子句,然后过滤:
from django.db.models import Exists, OuterRef
Users.objects<b>.annotate(</b>
<b>has_other=</b>Exists(
User.objects.filter(
<strong>pk__gt=OuterRef('pk')</strong>,
<strong>email=OuterRef('email')</strong>
)
)
<b>).filter(has_other=True)</b>
要对以下 table 使用自联接执行查询:
> 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
问题:
- 如何在 Django ORM 中编写此代码?
- 如果我想删除重复项以便在上面的示例中只得到 1 行,我如何在 Django 中实现它?
您可以检索 User
s,其中有另一个项目的主键大于(或小于)具有 Exists
subquery [Django-doc] 的用户的主键:
from django.db.models import Exists, OuterRef
Users.objects.filter(
Exists(
User.objects.filter(
<strong>pk__gt=OuterRef('pk')</strong>,
<strong>email=OuterRef('email')</strong>
)
)
)
如果您因此对这些调用 .delete()
,您将删除所有 User
,因为存在另一个具有更大主键的 Users
对象。
在 django-3.0 之前,应该将 Exists
子查询移动到 .annotate(…)
子句,然后过滤:
from django.db.models import Exists, OuterRef
Users.objects<b>.annotate(</b>
<b>has_other=</b>Exists(
User.objects.filter(
<strong>pk__gt=OuterRef('pk')</strong>,
<strong>email=OuterRef('email')</strong>
)
)
<b>).filter(has_other=True)</b>