VanJess - Touch the Floor
VanJess 는 Ivana와 Jessica Nwokike 자매로 구성된 나이지리아 R&B 듀오에요.
YouTube에서 커버 곡을 시작으로 경력을 시작어요. 그중 Drake 의 "Headlines"의 대박을 친 후에 음악 분야에 진지한 경력을 쌓기로 결정했조.
2011년에는 전문적으로 일을 하려고 사람도 고용하고 스튜디오에서 녹음도 했다고 하네요.
SQL에서 쿼리 아래 또 쿼리문을 작성하는 것을 서브 쿼리라고 한답니다.
그렇다면 django 역시 subquery를 갖추어야 겠조?
auth_user
모델과 OneToOne 관계로 연결된 UserParent
모델이 있다고 할게요.
아래 코드로 UserParent
모델에서 auth_user
를 가진 행을 모두 찾을 수 있어요.
>>> from django.db.models import Subquery
>>> users = User.objects.all()
>>> UserParent.objects.filter(user_id__in=Subquery(users.values('id')))
<QuerySet [<UserParent: UserParent object (2)>, <UserParent: UserParent object (5)>, <UserParent: UserParent object (8)>]>
다른 예제를 볼게요.
Category
모델의 각 행별로, 가장 선한 능력치를 가진 Hero
행을 구해 볼게요.
class Category(models.Model):
name = models.CharField(max_length=100)
class Hero(models.Model):
# ...
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
benevolence_factor = models.PositiveSmallIntegerField(
help_text="How benevolent this hero is?",
default=50
)
queryset으로 우리가 구하려는 가장~ 선한 능력치를 가진 영웅을 찾아볼게요.
hero_qs = Hero.objects.filter(
category=OuterRef("pk")
).order_by("-benevolence_factor")
Category.objects.all().annotate(
most_benevolent_hero=Subquery(
hero_qs.values('name')[:1]
)
)
여기서 보지 못했던 OuterRef()
가 보이네요. 일단은 넘어가고 추후에 다룰게요.
SELECT "entities_category"."id",
"entities_category"."name",
(SELECT U0."name"
FROM "entities_hero" U0
WHERE U0."category_id" = ("entities_category"."id")
ORDER BY U0."benevolence_factor" DESC
LIMIT 1) AS "most_benevolent_hero"
FROM "entities_category"
차근 차근 나눠서 살펴 볼게요.
hero_qs = Hero.objects.filter(
category=OuterRef("pk")
).order_by("-benevolence_factor")
Hero
모델의 항목들을 선한정도의값(benevolence_factor)
에 따라 내림차순으로 정렬하여 선택해요. 그리고 category=OuterRef("pk")
를 이용해 이 선택이 서브쿼리
로 사용될 수 있도록 준비합니다.
그 뒤 most_benevolent_hero=Subquery(hero_qs.values('name')[:1]) 로 서브쿼리에 별칭을 붙여 Category 쿼리셋 안에서 사용합니다. 이 때, hero_qs.values('name')[:1] 는 서브쿼리에서 첫 번째 행의 name 필드를 구하는 코드입니다.