programing

장고의 aggregate() 대 주석()

linuxpc 2023. 6. 5. 23:42
반응형

장고의 aggregate() 대 주석()

장고스QuerySet두 가지 방법이 있습니다.annotate그리고.aggregate설명서에는 다음과 같이 나와 있습니다.

aggregate()와 달리 주석()은 끝 절이 아닙니다.주석() 절의 출력은 QuerySet입니다.https://docs.djangoproject.com/en/4.1/topics/db/aggregation/ #쿼리 집합의 각 항목에 대한 인증서 생성

그들 사이에 또 다른 차이점이 있습니까?그렇지 , 왜 그않면다지왜렇만약?왜, ▁does?aggregate존재합니까?

문서에서 인용한 내용보다는 예제 쿼리에 중점을 두겠습니다. Aggregate전체 쿼리 세트에 대한 값을 계산합니다. Annotate쿼리 세트의 각 항목에 대한 요약 값을 계산합니다.

집계

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}

쿼리 집합에 있는 모든 책의 평균 가격이 들어 있는 사전을 반환합니다.

주석

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

q책의 쿼리 집합이지만 각 책에는 저자 수에 대한 주석이 달렸습니다.

Aggregate Aggregate는 전체 쿼리 집합에 걸쳐 결과(요약) 값을 생성합니다.집계는 행 집합에서 단일 값을 가져오기 위해 행 집합에서 작동합니다.(예: 행 집합의 모든 가격 합계).Aggregate는 전체 QuerySet에 적용되며 전체 QuerySet에 걸쳐 결과(요약) 값을 생성합니다.

모델 내:

class Books(models.Model):
    name = models.CharField(max_length=100)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=3)

셸 내:

>>> Books.objects.all().aggregate(Avg('price'))
# Above code will give the Average of the price Column 
>>> {'price__avg': 34.35}

주석 주석: 쿼리 집합의 각 개체에 대해 독립적인 요약을 생성합니다.(QuerySet에서 각 개체를 반복하고 적용 작업을 수행할 수 있습니다.)

모델 내:

class Video(models.Model):
    name = models.CharField(max_length=52, verbose_name='Name')
    video = models.FileField(upload_to=document_path, verbose_name='Upload 
               video')
    created_by = models.ForeignKey(User, verbose_name='Created by', 
                       related_name="create_%(class)s")
    user_likes = models.ManyToManyField(UserProfile, null=True, 
                  blank=True, help_text='User can like once', 
                         verbose_name='Like by')

뷰:

videos = Video.objects.values('id', 'name','video').annotate(Count('user_likes',distinct=True)

보기에서 각 비디오에 대해 좋아요를 계산합니다.

이것이 주요 차이점이지만, 애그리게이트는 주석보다 더 큰 규모로 작동합니다.주석은 본질적으로 쿼리 집합의 개별 항목과 관련되어 있습니다.를 실행하는 경우Count다대다 필드와 같은 것에 대한 주석을 사용하면 쿼리 집합의 각 멤버에 대한 개별 카운트(추가된 속성)를 얻을 수 있습니다.그러나 집계에 대해 동일한 작업을 수행할 경우 쿼리 집합의 모든 구성원에 대한 모든 관계(중복된 관계도 포함)를 계산하고 이를 하나의 값으로 반환합니다.

  • aggregate()모형 열의 모든 값을 계산할 수 있습니다.*사전이 반환됩니다.

  • 주석()은 모델의 모든 하위 열 외래 키를 외래 키로 계산할 수 있습니다.

*Avg(), Count(), Max(), Min(), Sum() 등과 함께 사용할 수 있습니다.aggregate()그리고.annotate().

예를 들어, 다음과 같은 것들이 있습니다.Category그리고.Product아래 모델:

# "models.py"

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=20)

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    price = models.DecimalField(decimal_places=2, max_digits=5)

그리고, 있습니다.Category그리고.Product아래 관리자:

# "admin.py"

from django.contrib import admin
from .models import Category, Product 

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ('id', 'name')
    ordering = ('id',)

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ('id', 'category_id', 'category', 'name', 'price')
    ordering = ('id',)

아래에는 두 가지 범주가 있습니다.

여기에 이미지 설명 입력

아래의 5가지 제품이 있습니다.

여기에 이미지 설명 입력

그리고, 있습니다.test아래 보기:

# "views.py"

from .models import Category, Product
from django.http import HttpResponse
from django.db.models import Avg
from django.db.models import Count
from django.db.models import Max
from django.db.models import Min
from django.db.models import Sum

def test(request):
    return HttpResponse("Test")

먼저 설명드리겠습니다.aggregate().

aggregate »:

이제, 나는 달립니다.test있는 뷰 및 평균(), 카운트(), 최대(), 최소()합계()aggregate()아래와 같이:

# "views.py"

# ...

def test(request):

    print(Product.objects.aggregate(Avg('id')))
    print(Product.objects.aggregate(Count('id')))
    print(Product.objects.aggregate(Max('id')))
    print(Product.objects.aggregate(Min('id')))
    print(Product.objects.aggregate(Sum('id')))
    print()
    print(Product.objects.aggregate(Avg('category')))
    print(Product.objects.aggregate(Count('category')))
    print(Product.objects.aggregate(Max('category')))
    print(Product.objects.aggregate(Min('category')))
    print(Product.objects.aggregate(Sum('category')))
    print()
    print(Product.objects.aggregate(Avg('price')))
    print(Product.objects.aggregate(Count('price')))
    print(Product.objects.aggregate(Max('price')))
    print(Product.objects.aggregate(Min('price')))
    print(Product.objects.aggregate(Sum('price')))
    
    return HttpResponse("Test")

그런 다음 아래 사전이 콘솔에 출력됩니다.

{'id__avg': 3.0}
{'id__count': 5}
{'id__max': 5}
{'id__min': 1}
{'id__sum': 15}

{'category__avg': 1.4}
{'category__count': 5}
{'category__max': 2}
{'category__min': 1}
{'category__sum': 7}

{'price__avg': Decimal('30.0000000000000000')}
{'price__count': 5}
{'price__max': Decimal('50.00')}
{'price__min': Decimal('10.00')}
{'price__sum': Decimal('150.00')}

그리고.aggregate()는 여러 종류의 열 및 함수를 임의의 순서로 사용할 수 있으며, 여러 종류의 동일한 열 및 함수를 사용할 수 있으며 아래와 같은 열 및 함수는 사용할 수 없습니다.*동일한 여러 종류의 열과 함수가 하나의 열로 만들어지지 않으며 함수는 빈 사전을 얻습니다.

# "views.py"

# ...

def test(request):
    # Multiple kinds of columns and functions in any order
    print(
        Product.objects.aggregate(
            Max('price'), Max('category'), Sum('id'), Min('id')
        )
    )

    # The multiple same kind of columns and functions
    print(
        Product.objects.aggregate(
            Sum('price'), Sum('price'), Sum('price')
        )
    )

    # No columns and functions
    print(Product.objects.aggregate())
        
    return HttpResponse("Test")

그런 다음 아래 사전이 콘솔에 출력됩니다.

{'price__max': Decimal('50.00'), 'category__max': 2, 'id__sum': 15, 'id__min': 1}
{'price__sum': Decimal('150.00')}
{}

그리고.Max()그리고.Min()아래는 비선택 유형을 허용할 수 있습니다.

# "views.py"

# ...

def test(request):

    print(Product.objects.aggregate(Count('name')))
    print(Product.objects.aggregate(Max('name')))
    print(Product.objects.aggregate(Min('name')))
        
    return HttpResponse("Test")

그런 다음 아래 사전이 콘솔에 출력됩니다.

{'name__count': 5}
{'name__max': 'Tea'}
{'name__min': 'Apple'}

그렇지만,Avg()그리고.Sum()아래는 비선택 유형을 허용할 수 없습니다.

# "views.py"

# ...

def test(request):

    print(Product.objects.aggregate(Avg('name')))
    print(Product.objects.aggregate(Sum('name')))
        
    return HttpResponse("Test")

따라서 다음과 같은 오류가 발생합니다.

django.db.dll 파일ProgrammingError: 함수 avg(문자가 다름)가 존재하지 않습니다.

django.db.dll 파일프로그래밍 오류: 함수 합계(문자가 다름)가 존재하지 않습니다.

또한 아래와 같이 기본 키 이름을 변경할 수 있습니다.

# "views.py"

# ...

def test(request):

    print(Product.objects.aggregate(priceAve=Avg('price')))
    print(Product.objects.aggregate(priceCount=Count('price')))
    print(Product.objects.aggregate(priceMax=Max('price')))
    print(Product.objects.aggregate(priceMin=Min('price')))
    print(Product.objects.aggregate(priceSum=Sum('price')))
        
    return HttpResponse("Test")

그런 다음 기본 키 이름이 다음과 같이 변경됩니다.

{'priceAve': Decimal('30.0000000000000000')}
{'priceCount': 5}
{'priceMax': Decimal('50.00')}
{'priceMin': Decimal('10.00')}
{'priceSum': Decimal('150.00')}

다음으로 에 대해 설명하겠습니다.annotate().

주석 달기(()):

이제, 나는 달립니다.test열이 있는 보기 및Avg(),Count(),Max(),Min()그리고.Sum()annotate()아래와 같이*당신은 그것을 넣을 필요합니다.__avg,__count,__max,__min그리고.__sum로.product__id,product__category그리고.product__price위해서Avg(),Count(),Max(),Min()그리고.Sum()각각:

# "views.py"

# ...

def test(request):

    qs = Category.objects.annotate(
        Avg('product__id'), 
        Count('product__id'), 
        Max('product__id'), 
        Min('product__id'), 
        Sum('product__id')
    ).order_by('pk')

    for obj in qs:
        print(
            obj.id, 
            obj.name, 
            obj.product__id__avg, 
            obj.product__id__count, 
            obj.product__id__max, 
            obj.product__id__min, 
            obj.product__id__sum
        )

    print()

    qs = Category.objects.annotate(
        Avg('product__category'), 
        Count('product__category'), 
        Max('product__category'), 
        Min('product__category'), 
        Sum('product__category')
    ).order_by('pk')

    for obj in qs:
        print(
            obj.id, 
            obj.name, 
            obj.product__category__avg, 
            obj.product__category__count, 
            obj.product__category__max, 
            obj.product__category__min, 
            obj.product__category__sum
        )

    print()

    qs = Category.objects.annotate(
        Avg('product__price'), 
        Count('product__price'), 
        Max('product__price'), 
        Min('product__price'), 
        Sum('product__price')
    ).order_by('pk')

    for obj in qs:
        print(
            obj.id, 
            obj.name, 
            obj.product__price__avg, 
            obj.product__price__count, 
            obj.product__price__max, 
            obj.product__price__min, 
            obj.product__price__sum
        )
    
    return HttpResponse("Test")

그런 다음 아래의 내용이 콘솔에 출력됩니다.

1 Food 2.0 3 3 1 6
2 Drink 4.5 2 5 4 9

1 Food 1.0 3 1 1 3
2 Drink 2.0 2 2 2 4

1 Food 20.0000000000000000 3 30.00 10.00 60.00
2 Drink 45.0000000000000000 2 50.00 40.00 90.00

그리고 아래 order_by('pk')가 없는 쿼리는 다음과 같이 순서를 내림차순으로 만듭니다.

# "views.py"

# ...

def test(request):

    qs = Category.objects.annotate(
        Avg('product__price'), 
        Count('product__price'), 
        Max('product__price'), 
        Min('product__price'), 
        Sum('product__price')
    ) # Without ".order_by('pk')"

    for obj in qs:
        print(
            obj.id, 
            obj.name, 
            obj.product__price__avg, 
            obj.product__price__count, 
            obj.product__price__max, 
            obj.product__price__min, 
            obj.product__price__sum
        )
    
    return HttpResponse("Test")

그런 다음 아래와 같이 순서가 하위로 이동합니다.

2 Drink 4.5 2 5 4 9
1 Food 2.0 3 3 1 6

그리고, 아래의 빈칸은id그리고.name속성:

# "views.py"

# ...

def test(request): 
                         # Empty "annotate()"
    qs = Category.objects.annotate().order_by('pk')

    for obj in qs:
        print(obj.id, obj.name)
        
    return HttpResponse("Test")

그런 다음 아래의 내용이 콘솔에 출력됩니다.

1 Food
2 Drink

그러나 아래의 빈칸은 다음을 포함하지 않습니다.__avg,__count,__max,__min그리고.__sum아래와 같은 속성:

# "views.py"

# ...

def test(request): 
                         # Empty "annotate()"
    qs = Category.objects.annotate().order_by('pk')
    
    for obj in qs:
        print(
            obj.product__price__avg,
            obj.product__price__count,
            obj.product__price__max,
            obj.product__price__min,
            obj.product__price__sum,
        )
        
    return HttpResponse("Test")

따라서 다음과 같은 오류가 발생합니다.

특성 오류: 'Category' 개체에 'product__price_avg' 특성이 없습니다.

특성 오류: 'Category' 개체에 'product__price_count' 특성이 없습니다.

특성 오류: 'Category' 개체에 'product__price_max' 특성이 없습니다.

특성 오류: 'Category' 개체에 'product__price_min' 특성이 없습니다.

특성 오류: 'Category' 개체에 'product__price_sum' 특성이 없습니다.

그리고.Max()그리고.Min()아래는 비선택 유형을 허용할 수 있습니다.

# "views.py"

# ...

def test(request):

    qs = Category.objects.annotate(
        Count('product__name'), 
        Max('product__name'), 
        Min('product__name'), 
    ).order_by('pk')

    for obj in qs:
        print( 
            obj.product__name__count, 
            obj.product__name__max, 
            obj.product__name__min, 
        )

    return HttpResponse("Test")

그런 다음 아래의 내용이 콘솔에 출력됩니다.

3 Orange Apple
2 Tea Milk

그렇지만,Avg()그리고.Sum()아래는 비선택 유형을 허용할 수 없습니다.

# "views.py"

# ...

def test(request):

    qs = Category.objects.annotate(
        Avg('product__name'),
        Sum('product__name')
    ).order_by('pk')

    for obj in qs:
        print( 
            obj.product__name__avg, 
            obj.product__name__sum
        )
        
    return HttpResponse("Test")

따라서 다음과 같은 오류가 발생합니다.

django.db.dll 파일ProgrammingError: 함수 avg(문자가 다름)가 존재하지 않습니다.

django.db.dll 파일프로그래밍 오류: 함수 합계(문자가 다름)가 존재하지 않습니다.

또한 다음과 같이 기본 특성 이름을 변경할 수 있습니다.

# "views.py"

# ...

def test(request):

    qs = Category.objects.annotate(
        productPriceAvg=Avg('product__price'), 
        productPriceCount=Count('product__price'), 
        productPriceMax=Max('product__price'), 
        productPriceMin=Min('product__price'), 
        productPriceSum=Sum('product__price')
    ).order_by('pk')

    for obj in qs:
        print(
            obj.id, 
            obj.name, 
            obj.productPriceAvg, 
            obj.productPriceCount, 
            obj.productPriceMax, 
            obj.productPriceMin, 
            obj.productPriceSum
        )
    
    return HttpResponse("Test")

그런 다음 아래의 내용이 콘솔에 출력됩니다.

1 Food 20.0000000000000000 3 30.00 10.00 60.00
2 Drink 45.0000000000000000 2 50.00 40.00 90.00

언급URL : https://stackoverflow.com/questions/7981837/aggregate-vs-annotate-in-django

반응형