Функции агрегации, специфичные для PostgreSQL

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

Примечание

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

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

Общие совокупные опционы

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

Агрегационные функции общего назначения

ArrayAgg

class ArrayAgg(expression, distinct=False, filter=None, default=None, ordering=(), **extra)[исходный код]

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

distinct

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

ordering

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

Примеры:

'some_field'
'-some_field'
from django.db.models import F
F('some_field').desc()

Не рекомендуется, начиная с версии 4.0: Если строк нет и default не предоставлено, ArrayAgg возвращает пустой список вместо None. Это поведение устарело и будет удалено в Django 5.0. Если вам это нужно, явно установите default в Value([]).

BitAnd

class BitAnd(expression, filter=None, default=None, **extra)[исходный код]

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

BitOr

class BitOr(expression, filter=None, default=None, **extra)[исходный код]

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

BitXor

New in Django 4.1.
class BitXor(expression, filter=None, default=None, **extra)[исходный код]

Возвращает int побитового XOR всех не нулевых входных значений, или default, если все значения равны null. Требуется PostgreSQL 14+.

BoolAnd

class BoolAnd(expression, filter=None, default=None, **extra)[исходный код]

Возвращает True, если все входные значения истинны, default, если все значения равны null или отсутствуют, иначе 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, если все значения равны null или отсутствуют, иначе 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 или default, если значений нет. Результат можно запросить с помощью key and index lookups.

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}
]}]>

Не рекомендуется, начиная с версии 4.0: Если строк нет и default не предоставлено, JSONBAgg возвращает пустой список вместо None. Это поведение устарело и будет удалено в Django 5.0. Если вам это нужно, явно установите default в Value('[]').

StringAgg

class StringAgg(expression, delimiter, distinct=False, filter=None, default=None, ordering=())[исходный код]

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

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'
}]>

Не рекомендуется, начиная с версии 4.0: Если строк нет и default не предоставлено, StringAgg возвращает пустую строку вместо None. Это поведение устарело и будет удалено в Django 5.0. Если вам это нужно, явно установите default в Value('').

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

y и x

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

Corr

class Corr(y, x, filter=None, default=None)[исходный код]

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

CovarPop

class CovarPop(y, x, sample=False, filter=None, default=None)[исходный код]

Возвращает ковариацию популяции в виде float, или default, если нет ни одной совпадающей строки.

sample

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

RegrAvgX

class RegrAvgX(y, x, filter=None, default=None)[исходный код]

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

RegrAvgY

class RegrAvgY(y, x, filter=None, default=None)[исходный код]

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

RegrCount

class RegrCount(y, x, filter=None)[исходный код]

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

Примечание

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

RegrIntercept

class RegrIntercept(y, x, filter=None, default=None)[исходный код]

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

RegrR2

class RegrR2(y, x, filter=None, default=None)[исходный код]

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

RegrSlope

class RegrSlope(y, x, filter=None, default=None)[исходный код]

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

RegrSXX

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}
Вернуться на верх