카테고리 없음

Django_Aggregation

황성안 2021. 4. 3. 23:03
728x90

Django_Aggregation

Joins and aggregates

Aggregation

QuerySet API reference - annotate()

QuerySet API reference - Aggregation functions


Annotate

  • Annotate calculates summary values for each item in the queryset.
  • '주석을 달다' 라는 사전적 의미
  • 필드를 하나 만들고 거기에 '어떤 내용'을 채워 넣는다.
  • 컬럼 하나를 추가하는 것과 같다.

Movie 모델과 Comment 모델이 1:N 관계

한 영화의 댓글 평균 값

from django.db.models import Avg

movie = Movie.objects.annotate(score_avg=Avg('comment__score')).get(pk=movies_pk)
  • 현재 Comment 모델 테이블이 다음과 같다면,
idcontentscoremovie_id
1짱짱102
2고양이졸귀탱61
3마블 명작81
4어벤져스11

movie_id가 1 (.get(pk=))이면서, comment 테이블의 score 컬럼의(comment__score) 평균(Avg)을 score_avg 라는 칼럼으로 추가적으로 만들어 붙여서(annotate) 결과를 받아보겠다.

  • 해당 sql 결과 조회하게 되는 table은 다음과 같이 작성된다. (Movie 테이블의 원본에는 변화가 없다.)
idtitleaudienceposter_urldescriptiongenre_idscore_avg
1캡틴 마블3035808Https://캡틴 마블..95



모든 영화의 댓글 평균 값

movies = Movie.objects.annotate(score_avg=Avg('comment__score'))
  • 대응되는 SQL 문

    SELECT
    "movies_movie"."id", "movies_movie"."genre_id", "movies_movie"."title", "movies_movie"."audience", "movies_movie"."poster_url", "movies_movie"."description", AVG("movies_score"."score") AS "score_avg"
    FROM "movies_movie" LEFT OUTER JOIN "movies_comment" ON ("movies_movie"."id" = "movies_comment"."movie_id") GROUP BY "movies_movie"."id", "movies_movie"."genre_id", "movies_movie"."title", "movies_movie"."audience", "movies_movie"."poster_url", "movies_movie"."description"
    
  • 현재 Comment 테이블이 다음과 같다면,
idcontentscoremovie_id
1짱짱102
2고양이졸귀탱61
3마블 명작81
4어벤져스11

Comment 테이블의 score 컬럼의(comment__score) 평균(Avg)을 score_avg 라는 칼럼으로 추가적으로 붙여서(annotate) 모든 데이터의 결과를 받아보겠다.

  • 해당 sql 결과 조회하게 되는 table은 다음과 같이 작성된다. (Movie 테이블의 원본에는 변화가 없다.)
idtitleaudienceposter_urldescriptiongenre_idscore_avg
1캡틴 마블3035808https://캡틴 마블..95
2항거:유관순이야기1041939https:.....310
...      
  • 따라서, 템플릿에서 다음과 같이 작성할 수 있다.

    <!-- detail.html -->
    
    <h4>종합 평점 : {{ movie.score_avg }}</h4>
    
    <!-- index.html -->
      
    {% for movie in movies %}
      <a href="{% url 'movies:detail' movie.pk %}">{{ movie.title }}</a><br>
      <p>종합 평점 : {{ movie.score_avg }}</p>
      <img src="{{ movie.poster_url }}" alt="poster">
      <hr>
    {% endfor %}
    



Aggregate

  • Aggregate calculates values for the entire queryset.
  • 무언가를 '종합', '집합', '합계' 등의 사전적 의미
  • returns a dictionary of name-value pairs.
  • 특정 필드 전체의 합, 평균, 개수 등을 계산할 때 사용한다.

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}
  • Book 모델의 price 컬럼 값의 평균
  • 즉, 모든 도서의 평균 값 ('average_price')
728x90