• 3.1
  • 3.2
  • 6.1
  • Версия документации: 5.0

Специальные функции агрегирования PostgreSQL

Эти функции доступны из модуля django.contrib.postgres.aggregates. Более подробно они описаны в Документации PostgreSQL.

Примечание

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

>>> SomeModel.objects.aggregate(arr=ArrayAgg("somefield"))
{'arr': [0, 1, 2]}

Общие варианты агрегатов

Все агрегаты имеют ключевой аргумент filter, а большинство из них также имеют ключевой аргумент default.

Функции агрегирования общего назначения

ArrayAgg

class ArrayAgg(expression, distinct=False, filter=None, default=None, ordering=(), **extra)

Возвращает список значений, включая значения NULL, объединенные в массив, или значение по умолчанию, если значений нет.

distinct

Необязательный логический аргумент, определяющий, будут ли значения массива различны. По умолчанию установлено значение «False».

ordering

Необязательная строка имени поля (с необязательным префиксом "-", который указывает порядок убывания) или выражение (или кортеж или список строк и/или выражений), которое определяет порядок элементов в списке результатов.

Например:

from django.db.models import F

ArrayAgg("a_field", ordering="-some_field")
ArrayAgg("a_field", ordering=F("some_field").desc())
Changed in Django 5.0:

В более старых версиях, если строк нет и не указан default, ArrayAgg`` возвращал пустой список вместо None. Если вам это нужно, явно установите для default значение Value([]).

БитИ

class BitAnd(expression, filter=None, default=None, **extra)

Возвращает int побитового И для всех ненулевых входных значений или по умолчанию, если все значения равны нулю.

БитОр

class BitOr(expression, filter=None, default=None, **extra)

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

БитКсор

class BitXor(expression, filter=None, default=None, **extra)

Возвращает целое число побитового исключающего ИЛИ всех ненулевых входных значений или значение по умолчанию, если все значения равны нулю. Требуется PostgreSQL 14+.

BoolAnd

class BoolAnd(expression, filter=None, default=None, **extra)

Возвращает True, если все входные значения истинны, default, если все значения равны нулю или если значений нет, в противном случае False.

Пример использования:

class Comment(models.Model):
    body = models.TextField()
    published = models.BooleanField()
    rank = models.IntegerField()
>>> from django.db.models import Q
>>> from django.contrib.postgres.aggregates import BoolAnd
>>> Comment.objects.aggregate(booland=BoolAnd("published"))
{'booland': False}
>>> Comment.objects.aggregate(booland=BoolAnd(Q(rank__lt=100)))
{'booland': True}

BoolOr

class BoolOr(expression, filter=None, default=None, **extra)

Возвращает True, если хотя бы одно входное значение истинно, default, если все значения равны нулю или если значений нет, в противном случае возвращает False.

Пример использования:

class Comment(models.Model):
    body = models.TextField()
    published = models.BooleanField()
    rank = models.IntegerField()
>>> from django.db.models import Q
>>> from django.contrib.postgres.aggregates import BoolOr
>>> Comment.objects.aggregate(boolor=BoolOr("published"))
{'boolor': True}
>>> Comment.objects.aggregate(boolor=BoolOr(Q(rank__gt=2)))
{'boolor': False}

JSONBAgg

class JSONBAgg(expressions, distinct=False, filter=None, default=None, ordering=(), **extra)

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

distinct

Необязательный логический аргумент, определяющий, будут ли значения массива различны. По умолчанию установлено значение «False».

ordering

Необязательная строка имени поля (с необязательным префиксом "-", который указывает порядок убывания) или выражение (или кортеж или список строк и/или выражений), которое определяет порядок элементов в списке результатов.

Примеры такие же, как для ArrayAgg.ordering.

Пример использования:

class Room(models.Model):
    number = models.IntegerField(unique=True)


class HotelReservation(models.Model):
    room = models.ForeignKey("Room", on_delete=models.CASCADE)
    start = models.DateTimeField()
    end = models.DateTimeField()
    requirements = models.JSONField(blank=True, null=True)
>>> from django.contrib.postgres.aggregates import JSONBAgg
>>> Room.objects.annotate(
...     requirements=JSONBAgg(
...         "hotelreservation__requirements",
...         ordering="-hotelreservation__start",
...     )
... ).filter(requirements__0__sea_view=True).values("number", "requirements")
<QuerySet [{'number': 102, 'requirements': [
    {'parking': False, 'sea_view': True, 'double_bed': False},
    {'parking': True, 'double_bed': True}
]}]>
Changed in Django 5.0:

В более старых версиях, если строк нет и не указан default, JSONBAgg возвращал пустой список вместо None. Если вам это нужно, явно установите для default значение Value([]).

StringAgg

class StringAgg(expression, delimiter, distinct=False, filter=None, default=None, ordering=())

Возвращает входные значения, объединенные в строку, разделенную строкой-разделителем или строкой по умолчанию, если значений нет.

delimiter

Обязательный аргумент. Должна быть строка.

distinct

Необязательный логический аргумент, определяющий, будут ли объединенные значения различны. По умолчанию установлено значение «False».

ordering

Необязательная строка имени поля (с необязательным префиксом "-", который указывает порядок убывания) или выражение (или кортеж или список строк и/или выражений), которое определяет порядок элементов в результирующей строке.

Примеры такие же, как для ArrayAgg.ordering.

Пример использования:

class Publication(models.Model):
    title = models.CharField(max_length=30)


class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)
>>> article = Article.objects.create(headline="NASA uses Python")
>>> article.publications.create(title="The Python Journal")
<Publication: Publication object (1)>
>>> article.publications.create(title="Science News")
<Publication: Publication object (2)>
>>> from django.contrib.postgres.aggregates import StringAgg
>>> Article.objects.annotate(
...     publication_names=StringAgg(
...         "publications__title",
...         delimiter=", ",
...         ordering="publications__title",
...     )
... ).values("headline", "publication_names")
<QuerySet [{
    'headline': 'NASA uses Python', 'publication_names': 'Science News, The Python Journal'
}]>
Changed in Django 5.0:

В более старых версиях, если строк нет и не указано default, StringAgg возвращал пустую строку вместо None. Если вам это нужно, явно установите default в Value("").

Агрегатные функции для статистики

y и x

Аргументы y и x для всех этих функций могут быть именем поля или выражением, возвращающим числовые данные. Оба необходимы.

Корр

class Corr(y, x, filter=None, default=None)

Возвращает коэффициент корреляции в виде числа с плавающей запятой или значения по умолчанию, если нет совпадающих строк.

КоварПоп

class CovarPop(y, x, sample=False, filter=None, default=None)

Возвращает ковариацию генеральной совокупности в виде числа с плавающей запятой или значения по умолчанию, если нет совпадающих строк.

sample

Необязательный. По умолчанию CovarPop возвращает общую ковариацию генеральной совокупности. Однако, если sample=True, возвращаемым значением будет ковариация генеральной совокупности выборки.

RegrAvgX

class RegrAvgX(y, x, filter=None, default=None)

Возвращает среднее значение независимой переменной (sum(x)/N) в виде числа с плавающей запятой или значения по умолчанию, если нет соответствующих строк.

RegrAvgY

class RegrAvgY(y, x, filter=None, default=None)

Возвращает среднее значение зависимой переменной (sum(y)/N) в виде числа с плавающей запятой или значения по умолчанию, если нет соответствующих строк.

РегрКаунт

class RegrCount(y, x, filter=None)

Возвращает целое число, определяющее количество входных строк, в которых оба выражения не равны нулю.

Примечание

Аргумент default не поддерживается.

РегрИнтерцепт

class RegrIntercept(y, x, filter=None, default=None)

Возвращает точку пересечения по оси Y линейного уравнения метода наименьших квадратов, определенного парами (x, y) как float или default, если нет совпадающих строк.

РегрР2

class RegrR2(y, x, filter=None, default=None)

Возвращает квадрат коэффициента корреляции в виде числа с плавающей запятой или значения по умолчанию, если совпадающих строк нет.

RegrSlope

class RegrSlope(y, x, filter=None, default=None)

Возвращает наклон линейного уравнения методом наименьших квадратов, определенного парами (x, y) в виде числа с плавающей запятой или значения по умолчанию, если нет совпадающих строк.

РегрSXX

class RegrSXX(y, x, filter=None, default=None)

Возвращает sum(x^2) - sum(x)^2/N («сумма квадратов» независимой переменной) как float или default, если нет подходящих строк.

RegrSXY

class RegrSXY(y, x, filter=None, default=None)

Возвращает sum(x*y) - sum(x) * sum(y)/N («сумма произведений» независимой переменной, зависящей от времени) как float или default, если нет совпадающих строк.

RegrSYY

class RegrSYY(y, x, filter=None, default=None)

Возвращает sum(y^2) - sum(y)^2/N («сумма квадратов» зависимой переменной) как float или default, если нет подходящих строк.

Примеры использования

Мы будем использовать этот пример таблицы:

| FIELD1 | FIELD2 | FIELD3 |
|--------|--------|--------|
|    foo |      1 |     13 |
|    bar |      2 | (null) |
|   test |      3 |     13 |

Вот несколько примеров некоторых функций агрегирования общего назначения:

>>> TestModel.objects.aggregate(result=StringAgg("field1", delimiter=";"))
{'result': 'foo;bar;test'}
>>> TestModel.objects.aggregate(result=ArrayAgg("field2"))
{'result': [1, 2, 3]}
>>> TestModel.objects.aggregate(result=ArrayAgg("field1"))
{'result': ['foo', 'bar', 'test']}

В следующем примере показано использование статистических агрегатных функций. Основная математика описываться не будет (вы можете прочитать об этом, например, в wikipedia):

>>> TestModel.objects.aggregate(count=RegrCount(y="field3", x="field2"))
{'count': 2}
>>> TestModel.objects.aggregate(
...     avgx=RegrAvgX(y="field3", x="field2"), avgy=RegrAvgY(y="field3", x="field2")
... )
{'avgx': 2, 'avgy': 13}
Back to Top