JavaRush /Курсы /Модуль 3: Django /Основные агрегатные функции: Sum, Avg, Count

Основные агрегатные функции: Sum, Avg, Count

Модуль 3: Django
10 уровень , 2 лекция
Открыта

Давайте углубимся в изучение основных агрегатных функций таких как Sum, Avg и Count. Эти инструменты являются базовыми кирпичиками, которые помогают нам собирать полезную статистику из данных веб-приложения.

Представьте, что у вас есть интернет-магазин и нужно узнать, сколько всего заказов оформлено (Count), какая у них средняя стоимость (Avg) или какова общая сумма всех заказов (Sum). Без агрегатных функций это можно было бы сделать вручную:

orders = Order.objects.all()
total_orders = len(orders)
total_sum = sum(order.price for order in orders)
avg_sum = total_sum / total_orders if total_orders > 0 else 0

Красиво? Ну, такое... Эффективно? Не слишком-то! Django ORM позволяет делегировать такие задачи базе данных, где эти операции выполняются быстрее и с меньшими затратами.

Основные агрегатные функции

Давайте разбираться с каждой из основных функций по очереди. Запаситесь чаем/кофе и хорошим настроением, впереди много кода!

1. Count: подсчёт записей

Когда вы хотите узнать просто количество записей в базе данных, на помощь приходит Count. Это самая простая и часто используемая функция.

Пример:

Начнем с простого. Допустим, у нас есть модель Order:

# models.py
from django.db import models

class Order(models.Model):
    total_price = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)

Чтобы узнать, сколько у нас всего заказов, используем aggregate() с Count:

from django.db.models import Count

result = Order.objects.aggregate(total_orders=Count('id'))
print(result)  # {'total_orders': 42}

Здесь 'id' указывает на поле, по которому мы считаем записи. Возвращается словарь, где ключ — это имя, которое вы дали вашему агрегату. В данном случае это total_orders.

Подсчёт уникальных значений

Иногда хочется узнать, сколько уникальных значений есть в каком-либо поле. Например, сколько уникальных дат, когда были сделаны заказы.

unique_dates = Order.objects.aggregate(unique_dates=Count('created_at', distinct=True))
print(unique_dates)  # {'unique_dates': 7}

Флаг distinct=True позволяет игнорировать дубликаты.

2. Sum: сумма значений

Теперь давайте подсчитаем общую сумму всех заказов. Для этого используем функцию Sum.

Пример:

from django.db.models import Sum

result = Order.objects.aggregate(total_revenue=Sum('total_price'))
print(result)  # {'total_revenue': Decimal('3000.50')}

Зачастую вам нужно будет работать с числовыми типами данных вроде IntegerField или DecimalField. Sum отлично работает с обоими.

В реальных приложениях часто надо вычислить сумму по какому-то условию. Например, сумму заказов, созданных в определённый день.

from django.utils.timezone import now

today = now().date()
daily_revenue = Order.objects.filter(created_at__date=today).aggregate(total_revenue=Sum('total_price'))
print(daily_revenue)  # {'total_revenue': Decimal('500.00')}

Здесь мы фильтруем заказы перед применением aggregate().

3. Avg: среднее значение

Теперь давайте определим среднюю стоимость заказа. Для этого используем функцию Avg.

Пример:

from django.db.models import Avg

result = Order.objects.aggregate(average_price=Avg('total_price'))
print(result)  # {'average_price': Decimal('142.50')}

Среднее значение — это полезная функция, если вы хотите анализировать тенденции данных. Например, если средняя стоимость заказа растёт, это может быть индикатором увеличения объёмов продаж.

Сравнение результатов

Давайте теперь соберём всё вместе. К примеру, нам нужно сразу посчитать:

  • Общее количество заказов.
  • Общую сумму всех заказов.
  • Среднюю стоимость заказа.

Мы можем сделать это в одном запросе:

result = Order.objects.aggregate(
    total_orders=Count('id'),
    total_revenue=Sum('total_price'),
    average_price=Avg('total_price')
)
print(result)
# {'total_orders': 42, 'total_revenue': Decimal('3000.50'), 'average_price': Decimal('142.50')}

Это удобно и эффективно: один вызов базы данных для получения трёх разных метрик.

Практическое задание

Попробуйте самостоятельно реализовать следующий сценарий. У вас есть модель Product:

# models.py
class Product(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.IntegerField()  # количество на складе

Ваши задачи:

  1. Подсчитать общее количество товаров.
  2. Подсчитать общую стоимость всех товаров на складе (цена * количество на складе).
  3. Найти среднюю цену товара.

Подсказка: для выполнения второго задания вам понадобится использование аннотаций с annotate() (мы будем говорить об этом дальше), но вы можете начать решение, используя только aggregate().

Типичные ошибки при работе с агрегатами

Когда начинаешь работать с агрегатами, можно столкнуться с несколькими нюансами.

Например, если вы пытаетесь передать поле, которое отсутствует в модели, Django бросит вам исключение. Убедитесь, что указанное поле существует и корректно написано.

Также, если поле, используемое для агрегатов, содержит NULL значения, база данных может игнорировать их при вычислениях. Если вы хотите включить такие записи, используйте default для null значений, чтобы избежать неожиданных результатов.

# Убедитесь, что поле total_price всегда числовое
Order.objects.aggregate(total_revenue=Sum('total_price', default=0))

Применение в реальной жизни

В реальной жизни агрегатные функции активно используются для построения отчётов, метрик для дашбордов или же для выполнения аналитики прямо в веб-приложении.

Например:

  • Подсчёт количества новых пользователей за неделю Count.
  • Общее количество проданных товаров Sum.
  • Средний чек за день Avg.

Это те самые задачи, которые делают ваше приложение полезным для бизнеса.

И последнее: не забывайте следить за производительностью запросов, особенно если работаете с большими данными. Используйте возможности базы данных на полную мощность, но помните, что грамотная индексация и настройка базы часто спасают от неожиданного снижения производительности.

1
Задача
Модуль 3: Django, 10 уровень, 2 лекция
Недоступна
Подсчёт средней цены продуктов
Подсчёт средней цены продуктов
1
Задача
Модуль 3: Django, 10 уровень, 2 лекция
Недоступна
Подсчёт общей стоимости заказов
Подсчёт общей стоимости заказов
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ