본문 바로가기

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 함수 설명과 예

 

Django - ORM aggregation 함수 설명과 예

앞서 살펴본 Group by 하는 결과에 많이 사용되는 집계함수에 대해서도 잠깐 살펴보자. annotate() 구문 안에서 자주 사용되는 aggregation funcion 은 아래 처럼 몇가지를 사용할 수 있다. 장고 ORM에서 사

wiznxt.tistory.com

주의할 점이 있다.

https://amanokaze.github.io/blog/Django-Queryset-Groupby/

 

Django Queryset에서 MySQL DB의 Group by SQL문을 표현하는 방법

Various IT-based research space, django, cloud, machine learning, and so on.

amanokaze.github.io

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}]>

여러분들께서는 절대로 원하는 결과를 쉽게 얻어내지 못할 것입니다. 분명히 한계가 있는 구문이죠.

 

돈을 잘 모아야 sum :)

Pexels에서 Joslyn Pickens님의 사진: https://www.pexels.com/ko-kr/photo/5224948/

B로그0간

개발 관련 글과 유용한 정보를 공유하는 공간입니다.