跳转至

聚合函数

目前支持 6 种聚合函数。

  • count(distinct: bool = True) -> int

  • 存在() -> 布尔值

  • 总和(列)-> 任意

  • 平均值(列)-> 任意

  • 分钟(列)-> 任意

  • 最大(列)-> 任意

  • 查询集代理

    • QuerysetProxy.count(distinct=True) 方法
    • QuerysetProxy.exists() 方法
    • QuerysetProxy.sum(columns) 方法
    • QuerysetProxy.avg(columns) 方法
    • QuerysetProxy.min(column) 方法
    • QuerysetProxy.max(列) 方法

数数

count(distinct: bool = True) -> int

返回与给定条件匹配的行数(即应用过滤器和排除)。如果distinct为True(默认值),这将返回选定的主行数。如果为 False,则计数将是返回的总行数(包括一对多或多对多左 select_lated 表连接的额外行)。 False 是依赖于它的工作流的遗留(有缺陷的)行为。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Book(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=databases.Database(DATABASE_URL),
        metadata=sqlalchemy.MetaData(),
        tablename="book"
    )

    id: int = ormar.Integer(primary_key=True)
    title: str = ormar.String(max_length=200)
    author: str = ormar.String(max_length=100)
    genre: str = ormar.String(
        max_length=100,
        default="Fiction",
        choices=["Fiction", "Adventure", "Historic", "Fantasy"],
    )


# returns count of rows in db for Books model
no_of_books = await Book.objects.count()

存在

存在() -> 布尔值

返回一个布尔值以确认是否有符合给定条件的行(与过滤器和排除一起应用)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Book(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=databases.Database(DATABASE_URL),
        metadata=sqlalchemy.MetaData(),
        tablename="book"
    )

    id: int = ormar.Integer(primary_key=True)
    title: str = ormar.String(max_length=200)
    author: str = ormar.String(max_length=100)
    genre: str = ormar.String(
        max_length=100,
        default="Fiction",
        choices=["Fiction", "Adventure", "Historic", "Fantasy"],
    )


# returns a boolean value if given row exists
has_sample = await Book.objects.filter(title='Sample').exists()

和

总和(列)-> 任意

返回与给定条件匹配的行的列的总和值(应用过滤器,如果之前设置则排除)。

您可以传递一个或多个列名称,包括相关列。

截至目前,传递的每一列都是单独聚合的(因此 sum(col1+col2) 是不可能的,您可以使用 sum(col1, col2) ,然后在 python 中添加 2 个返回的总和)

您不能对非数字列求和。

如果对一列进行聚合,则直接返回单个值作为结果 如果对多列进行聚合,则返回包含 column: 结果对的字典

给定模型如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from typing import Optional

import databases
import ormar
import sqlalchemy
from tests.settings import DATABASE_URL

database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()


base_ormar_config = ormar.OrmarConfig(
    metadata=metadata,
    database=database,
)


class Author(ormar.Model):
    ormar_config = base_ormar_config.copy(tablename="authors", order_by=["-name"])

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Book(ormar.Model):

    ormar_config = base_ormar_config.copy(
        tablename="books", order_by=["year", "-ranking"]
    )

    id: int = ormar.Integer(primary_key=True)
    author: Optional[Author] = ormar.ForeignKey(Author)
    title: str = ormar.String(max_length=100)
    year: int = ormar.Integer(nullable=True)
    ranking: int = ormar.Integer(nullable=True)

示例用法可能如下所示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
author = await Author(name="Author 1").save()
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
await Book(title="Book 3", year=1923, ranking=5, author=author).save()

assert await Book.objects.sum("year") == 5773
result = await Book.objects.sum(["year", "ranking"])
assert result == dict(year=5773, ranking=9)

try:
    # cannot sum string column
    await Book.objects.sum("title")
except ormar.QueryDefinitionError:
    pass

assert await Author.objects.select_related("books").sum("books__year") == 5773
result = await Author.objects.select_related("books").sum(
    ["books__year", "books__ranking"]
)
assert result == dict(books__year=5773, books__ranking=9)

assert (
    await Author.objects.select_related("books")
    .filter(books__year__lt=1925)
    .sum("books__year")
    == 3843
)

平均

平均值(列)-> 任意

返回匹配给定条件的行的列的平均值(应用过滤器,如果之前设置则排除)。

您可以传递一个或多个列名称,包括相关列。

截至目前,传递的每一列都是单独聚合的(因此 sum(col1+col2) 是不可能的,您可以使用 sum(col1, col2) ,然后在 python 中添加 2 个返回的总和)

您不能对非数字列求平均值。

如果对一列进行聚合,则直接返回单个值作为结果 如果对多列进行聚合,则返回包含 column: 结果对的字典

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from typing import Optional

import databases
import ormar
import sqlalchemy
from tests.settings import DATABASE_URL

database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()


base_ormar_config = ormar.OrmarConfig(
    metadata=metadata,
    database=database,
)


class Author(ormar.Model):
    ormar_config = base_ormar_config.copy(tablename="authors", order_by=["-name"])

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Book(ormar.Model):

    ormar_config = base_ormar_config.copy(
        tablename="books", order_by=["year", "-ranking"]
    )

    id: int = ormar.Integer(primary_key=True)
    author: Optional[Author] = ormar.ForeignKey(Author)
    title: str = ormar.String(max_length=100)
    year: int = ormar.Integer(nullable=True)
    ranking: int = ormar.Integer(nullable=True)

示例用法可能如下所示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
author = await Author(name="Author 1").save()
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
await Book(title="Book 3", year=1923, ranking=5, author=author).save()

assert round(float(await Book.objects.avg("year")), 2) == 1924.33
result = await Book.objects.avg(["year", "ranking"])
assert round(float(result.get("year")), 2) == 1924.33
assert result.get("ranking") == 3.0

try:
    # cannot avg string column
    await Book.objects.avg("title")
except ormar.QueryDefinitionError:
    pass

result = await Author.objects.select_related("books").avg("books__year")
assert round(float(result), 2) == 1924.33
result = await Author.objects.select_related("books").avg(
    ["books__year", "books__ranking"]
)
assert round(float(result.get("books__year")), 2) == 1924.33
assert result.get("books__ranking") == 3.0

assert (
    await Author.objects.select_related("books")
    .filter(books__year__lt=1925)
    .avg("books__year")
    == 1921.5
)

分钟

分钟(列)-> 任意

返回匹配给定条件的行的列的最小值(与过滤器一起应用,如果之前设置则排除)。

您可以传递一个或多个列名称,包括相关列。

截至目前,传递的每一列都是单独聚合的(因此 sum(col1+col2) 是不可能的,您可以使用 sum(col1, col2) ,然后在 python 中添加 2 个返回的总和)

如果对一列进行聚合,则直接返回单个值作为结果 如果对多列进行聚合,则返回包含 column: 结果对的字典

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from typing import Optional

import databases
import ormar
import sqlalchemy
from tests.settings import DATABASE_URL

database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()


base_ormar_config = ormar.OrmarConfig(
    metadata=metadata,
    database=database,
)


class Author(ormar.Model):
    ormar_config = base_ormar_config.copy(tablename="authors", order_by=["-name"])

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Book(ormar.Model):

    ormar_config = base_ormar_config.copy(
        tablename="books", order_by=["year", "-ranking"]
    )

    id: int = ormar.Integer(primary_key=True)
    author: Optional[Author] = ormar.ForeignKey(Author)
    title: str = ormar.String(max_length=100)
    year: int = ormar.Integer(nullable=True)
    ranking: int = ormar.Integer(nullable=True)

示例用法可能如下所示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
author = await Author(name="Author 1").save()
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
await Book(title="Book 3", year=1923, ranking=5, author=author).save()

assert await Book.objects.min("year") == 1920
result = await Book.objects.min(["year", "ranking"])
assert result == dict(year=1920, ranking=1)

assert await Book.objects.min("title") == "Book 1"

assert await Author.objects.select_related("books").min("books__year") == 1920
result = await Author.objects.select_related("books").min(
    ["books__year", "books__ranking"]
)
assert result == dict(books__year=1920, books__ranking=1)

assert (
    await Author.objects.select_related("books")
    .filter(books__year__gt=1925)
    .min("books__year")
    == 1930
)

最大限度

最大(列)-> 任意

返回匹配给定条件的行的列的最大值(与过滤器一起应用,如果之前设置则排除)。

返回匹配给定条件的行的列的最小值(与过滤器一起应用,如果之前设置则排除)。

您可以传递一个或多个列名称,包括相关列。

截至目前,传递的每一列都是单独聚合的(因此 sum(col1+col2) 是不可能的,您可以使用 sum(col1, col2) ,然后在 python 中添加 2 个返回的总和)

如果对一列进行聚合,则直接返回单个值作为结果 如果对多列进行聚合,则返回包含 column: 结果对的字典

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from typing import Optional

import databases
import ormar
import sqlalchemy
from tests.settings import DATABASE_URL

database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()


base_ormar_config = ormar.OrmarConfig(
    metadata=metadata,
    database=database,
)


class Author(ormar.Model):
    ormar_config = base_ormar_config.copy(tablename="authors", order_by=["-name"])

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Book(ormar.Model):

    ormar_config = base_ormar_config.copy(
        tablename="books", order_by=["year", "-ranking"]
    )

    id: int = ormar.Integer(primary_key=True)
    author: Optional[Author] = ormar.ForeignKey(Author)
    title: str = ormar.String(max_length=100)
    year: int = ormar.Integer(nullable=True)
    ranking: int = ormar.Integer(nullable=True)

示例用法可能如下所示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
author = await Author(name="Author 1").save()
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
await Book(title="Book 3", year=1923, ranking=5, author=author).save()

assert await Book.objects.max("year") == 1930
result = await Book.objects.max(["year", "ranking"])
assert result == dict(year=1930, ranking=5)

assert await Book.objects.max("title") == "Book 3"

assert await Author.objects.select_related("books").max("books__year") == 1930
result = await Author.objects.select_related("books").max(
    ["books__year", "books__ranking"]
)
assert result == dict(books__year=1930, books__ranking=5)

assert (
    await Author.objects.select_related("books")
    .filter(books__year__lt=1925)
    .max("books__year")
    == 1923
)

QuerysetProxy 方法

当直接访问相关的ManyToMany字段以及ReverseForeignKey时,返回相关模型的列表。

但同时它公开了 QuerySet API 的子集,因此您可以直接从父模型过滤、创建、选择相关模型等。

数数

与上面的 count 函数完全相同,但允许您从关系另一端的相关对象中选择列。

!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分

存在

与上面的存在函数完全相同,但允许您从关系另一端的相关对象中选择列。

和

与上面的 sum 函数完全相同,但允许您对关系另一端的相关对象的列进行求和。

平均

与上面的 avg 函数完全相同,但允许您对关系另一端的相关对象的列进行平均。

分钟

与上面的 min 函数完全相同,但允许您从关系另一端的相关对象中选择最少的列。

最大限度

与上面的 max 函数完全相同,但允许您从关系另一端的相关对象中选择最大列。

!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分