group by는 SQL에서 데이터를 그룹화하는 구문입니다.
장고 ORM에서는 values() 메소드를 사용하여 group by의 대상이 되는 컬럼을 지정할 수 있습니다.
이후 annotate() 함수로 집계된 데이터에서 집계 함수를 실행할 수 있습니다.
예를 들어, 다음과 같은 쿼리는 장고 ORM으로 다음과 같이 표현할 수 있습니다.
# SQL
SELECT name, COUNT(*) FROM test GROUP BY name;
# Django ORM
queryset = Test.objects.values('name').annotate(count=Count('*'))
위의 예제에서 values('name')은 GROUP BY name과 동일한 역할을 합니다.
이후 annotate(count=Count('*'))는 집계 함수인 COUNT(*)와 동일한 역할을 합니다.
annotate()는 장고 ORM에서 집계 함수를 사용할 때 사용하는 메소드입니다
annotate()는 여러 개의 집계 함수를 동시에 사용할 수도 있습니다. 예를 들어, 다음과 같은 쿼리는 장고 ORM으로 다음과 같이 표현할 수 있습니다.
# SQL
SELECT name, COUNT(*), AVG(age) FROM test GROUP BY name;
# Django ORM
queryset = Test.objects.values('name').annotate(count=Count('*'), avg_age=Avg('age'))
위의 예제에서 annotate(count=Count(''),avg_age=Avg('age'))는 집계 함수인 COUNT(*)와 AVG(age)와 동일한 역할을 합니다. 이때 count와 avg_age는 각각 계산된 값을 저장할 필드의 이름입니다.
2개 이상의 필드로 group by 를 하게되면, 아래 예를 가지고 이해해보자.
예를 들어 다음과 같은 Test 모델이 있다고 가정해 보겠습니다.
class Test(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
count = models.IntegerField()
이 모델에 다음과 같은 데이터가 저장되어 있다고 가정해 보겠습니다.
name | age | count |
---|---|---|
A | 10 | 1 |
A | 20 | 2 |
B | 10 | 3 |
B | 20 | 4 |
다음과 같은 쿼리를 실행하면 다음과 같은 결과가 반환됩니다.
# Django ORM
queryset = Test.objects.values('name', 'age').annotate(count=Count('*'))
# 결과
<QuerySet [{'name': 'A', 'age': 10, 'count': 1}, {'name': 'A', 'age': 20, 'count': 1}, {'name': 'B', 'age': 10, 'count': 1}, {'name': 'B', 'age': 20, 'count': 1}]>
위의 예제에서 values('name', 'age')는 GROUP BY name, age와 동일한 역할을 합니다. 이후 annotate(count=Count('*'))는 집계 함수인 COUNT(*)와 동일한 역할을 합니다.
Aggregation 함수는 다음 글에서 살펴보자.
2023.05.01 - [IT/파이썬] - Django - ORM aggregation 함수 설명과 예
주의할 점이 있다.
https://amanokaze.github.io/blog/Django-Queryset-Groupby/
Order by 와 함께 쓰면 원하는 결과가 안나올 수 도 있다는...
categories = TB.objects.order_by('category_seq').values('category_seq').annotate(Count('category_seq'))
print(categories)
이런 식으로, QuerySets 결과를 먼저 order_by 등과 같이 정렬을 한 후 values - annotate(Count)를 하면 어떻게 될까요.
<QuerySet [{'category_seq': 1}, {'category_seq': 1}, {'category_seq': 1}, {'category_seq': 1}, {'category_seq': 1}, {'category_seq': 1}, {'category_seq': 1}, {'category_seq': 1}, {'category_seq': 2}]>
여러분들께서는 절대로 원하는 결과를 쉽게 얻어내지 못할 것입니다. 분명히 한계가 있는 구문이죠.
Pexels에서 Joslyn Pickens님의 사진: https://www.pexels.com/ko-kr/photo/5224948/
'IT > 파이썬' 카테고리의 다른 글
Django ORM - aggregation sum 결과가 0 인 결과 배제하기 (0) | 2023.05.04 |
---|---|
Django ORM - Group by 사용해서 Count, Sum, Avg 구하기 (0) | 2023.05.03 |
Django - ORM aggregation 함수 설명과 예 (0) | 2023.05.01 |
Django - Rest-framework API 서버 구현 with Django Ninja (0) | 2023.04.28 |
Django - response 객체에 쿼리스트링 추가 (0) | 2023.04.26 |