[Django] Django ORM

GreenBeanΒ·2021λ…„ 9μ›” 29일
0
post-thumbnail

Django ORM

Django ORM μ—μ„œ 집계 ν•¨μˆ˜μ™€ κ·Έλ£Ήν•‘(aggregate, group by)λ₯Ό μ‚¬μš©ν•˜λŠ” 방법

Tip! 집계 ν•¨μˆ˜

  • count() : NULL이 μ•„λ‹Œ λ ˆμ½”λ“œμ˜ 수
  • sum() : ν•„λ“œλͺ…μ˜ κ°’λ“€μ˜ 합계
  • avg() : ν•„λ“œλͺ…μ˜ κ°’λ“€μ˜ 평균
  • min() : ν•„λ“œλͺ…μ˜ κ°’ 쀑 κ°€μž₯ μž‘μ€ κ°’
  • max() : ν•„λ“œλͺ…μ˜ κ°’ 쀑 κ°€μž₯ 큰 κ°’

μ°Έκ³ ! count()λ₯Ό μ œμ™Έν•œ 수치λ₯Ό κ³„μ‚°ν•˜λŠ” 집계 ν•¨μˆ˜λŠ” NULL 값을 가진 ν–‰μ˜ λ°μ΄ν„°λŠ” λ¬΄μ‹œν•˜κ³  계산

aggregate()

  1. μ§€μ •ν•œ μΏΌλ¦¬μ…‹μ—μ„œ μ§€μ •ν•œ μ—΄μ˜ 집계 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜κ³  λ°˜ν™˜
  2. 일반적인 μΏΌλ¦¬μ…‹μ˜ λ©”μ„œλ“œμ™€ λ‹€λ₯΄κ²Œ μ‹€ν–‰ν•˜λ©΄ λ°”λ‘œ κ²°κ³Όλ₯Ό λ°˜ν™˜
# μ˜ˆμ‹œ μ½”λ“œ

from django.db.models import Sum

OrderList.objects.aggregate(total_price=Sum('price'))
>>> {'total_price': 488000}
  • μ˜ˆμ‹œ μ½”λ“œ
    • QuerySet이 μ•„λ‹Œ μ‹€ν–‰ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ μΏΌλ¦¬μ…‹μ˜ 맨 λ§ˆμ§€λ§‰μ— μž‘μ„±
    • values λ©”μ„œλ“œλ₯Ό μ΄μš©ν•œ group by 쿼리λ₯Ό μ‹€ν–‰ν•˜μ§€ μ•ŠμŒ
      • group by μ ˆμ„ μ‚¬μš©ν•˜λ €λ©΄ annotate λ©”μ„œλ“œλ₯Ό μ‚¬μš©

πŸ”₯ annotate()

  1. select λŒ€μƒμ˜ ν•„λ“œλͺ…을 λ³€κ²½
<from django.db import F

# labelμ—΄μ˜ 이름을 tag둜 λ³€κ²½
Article.objects.all().annotate(tag=F("label"))
  1. values λ©”μ„œλ“œμ™€ ν•¨κ»˜ μ‚¬μš©ν•˜μ—¬ group by, having μ ˆμ„ κ΅¬ν˜„
  • where 절과 having μ ˆμ— 지정할 ν•„ν„°λ₯Ό κ΅¬λΆ„ν•˜κ³  μž‘μ„±
  • values λ©”μ„œλ“œλ‘œ group by λŒ€μƒμ˜ 열을 μ§€μ •ν•˜κ³ , annotate ν•¨μˆ˜λ‘œ μ§‘κ³„λœ λ°μ΄ν„°μ—μ„œ 집계 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ κ°€λŠ₯
# μ˜ˆμ‹œ μ½”λ“œ

StudentGrade.objects
    		.filter(year=2020)
    		.values("class")
        	.annotate(student_count=Count("student_id"), score_average=Avg("score"))
    		.filter(student_count__gte=30)
    		.values("score_average")
  • μ˜ˆμ‹œ μ½”λ“œ
    • group by절 μ‚¬μš© μ „ where절의 필터링을 지정
      • 이 λ•Œ, μ™Έλž˜ν‚€λ₯Ό 가진 λͺ¨λΈμ˜ INNER JOIN을 μ‚¬μš©ν•  수 있음
    • values λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ group by 의 λŒ€μƒμ΄ λ˜λŠ” μ»¬λŸΌμ„ 지정
    • 집계 ν•¨μˆ˜λ‘œ 계산할 열을 지정
      • 이 λ•Œ, 지정할 μ—΄ λͺ… = μ§‘κ³„ν•¨μˆ˜(집계될 μ—΄ λͺ…) 으둜 지정
    • group byκ°€ μ§€μ •λœ QuerySet μ—μ„œ λ‹€μ‹œ 필터링을 지정
      • 이 λ•ŒλŠ” having 절둜 필터링
    • 집계 된 λ°μ΄ν„°μ—μ„œ 필터링 μ‹œμ—λŠ” lookup_expr 을 μ‚¬μš©ν•  수 있음
    • λ§ˆμ§€λ§‰μœΌλ‘œ select ν•  데이터λ₯Ό 선택
      • 선택사항 : score_average 만 μΆ”μΆœν•  경우

Tip! μΆ”κ°€ λ‚΄μš©

annotate()

Case == if .. elif .. else

  • 쑰건적인 annotate에 μ‚¬μš©ν•˜λŠ” ν΄λž˜μŠ€λŠ” Case와 Value, When
    • CaseλŠ” if elif elseλž‘ λΉ„μŠ·ν•˜λ‹€κ³  λ³Ό 수 있음
data = queryset.annotate(date=truncClass('date_joined'))
               .values('date')
               .annotate(active_num=Count(
                                        Case(
                                            When(
                                                id__in=active_ids,
                                                then="id",),),
                                        distinct=True,
                                    ),
                         active_num=Count(
                                        Case(
                                            When(
                                                id__in=more_active_ids,
                                                then="id",),)
                                        ,distinct=True,
                                    ),
                         deactive_num=Count(
                                        Case(
                                            When(
                                                id__in=deactive_ids,
                                                then="id",),),
                                        distinct=True,),)
               .order_by('date')
profile
🌱 Backend-Dev | hwaya2828@gmail.com

0개의 λŒ“κΈ€