下面记录的类为用户提供了一种方法,可以在 Django 中使用底层数据库提供的函数作为注解、聚合或过滤器。函数也是 表达式,所以它们可以和其他表达式一起使用和组合,比如 聚合函数。
我们将在每个函数的例子中使用以下模型:
class Author(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveIntegerField(null=True, blank=True)
alias = models.CharField(max_length=50, null=True, blank=True)
goes_by = models.CharField(max_length=50, null=True, blank=True)
我们通常不建议允许 null=True
为 CharField
,因为这允许字段有两个 Coalesce
,但它对下面的 Coalesce
例子很重要。
Cast
¶Cast
(expression, output_field)¶强制 expression
的结果类型为 output_field
的类型。
Usage example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cast
>>> Author.objects.create(age=25, name="Margaret Smith")
>>> author = Author.objects.annotate(
... age_as_float=Cast("age", output_field=FloatField()),
... ).get()
>>> print(author.age_as_float)
25.0
Coalesce
¶Coalesce
(*expressions, **extra)¶接受至少两个字段名或表达式的列表,并返回第一个非空值(注意,空字符串不被视为空值)。每个参数必须是同样的类型,因此混合文本和数字将导致数据库错误。
Usage examples:
>>> # Get a screen name from least to most public
>>> from django.db.models import Sum
>>> from django.db.models.functions import Coalesce
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(screen_name=Coalesce("alias", "goes_by", "name")).get()
>>> print(author.screen_name)
Maggie
>>> # Prevent an aggregate Sum() from returning None
>>> # The aggregate default argument uses Coalesce() under the hood.
>>> aggregated = Author.objects.aggregate(
... combined_age=Sum("age"),
... combined_age_default=Sum("age", default=0),
... combined_age_coalesce=Coalesce(Sum("age"), 0),
... )
>>> print(aggregated["combined_age"])
None
>>> print(aggregated["combined_age_default"])
0
>>> print(aggregated["combined_age_coalesce"])
0
警告
在 MySQL 上传递给 Coalesce
的 Python 值可能会被转换为不正确的类型,除非明确地转换为正确的数据库类型:
>>> from django.db.models import DateTimeField
>>> from django.db.models.functions import Cast, Coalesce
>>> from django.utils import timezone
>>> now = timezone.now()
>>> Coalesce("updated", Cast(now, DateTimeField()))
Collate
¶Collate
(expression, collation)¶Takes an expression and a collation name to query against.
For example, to filter case-insensitively in SQLite:
>>> Author.objects.filter(name=Collate(Value("john"), "nocase"))
<QuerySet [<Author: John>, <Author: john>]>
It can also be used when ordering, for example with PostgreSQL:
>>> Author.objects.order_by(Collate("name", "et-x-icu"))
<QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>
Greatest
¶Greatest
(*expressions, **extra)¶接受至少两个字段名或表达式的列表,并返回最大的值。每个参数必须是同样的类型,所以混合文本和数字会导致数据库错误。
使用实例:
class Blog(models.Model):
body = models.TextField()
modified = models.DateTimeField(auto_now=True)
class Comment(models.Model):
body = models.TextField()
modified = models.DateTimeField(auto_now=True)
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
>>> from django.db.models.functions import Greatest
>>> blog = Blog.objects.create(body="Greatest is the best.")
>>> comment = Comment.objects.create(body="No, Least is better.", blog=blog)
>>> comments = Comment.objects.annotate(last_updated=Greatest("modified", "blog__modified"))
>>> annotated_comment = comments.get()
annotated_comment.last_updated
将是 blog.modified
和 comment.modified
中最近的。
警告
当一个或多个表达式可能为 null
时,Greatest
的行为在不同的数据库之间有所不同。
Greatest
将返回最大的非空表达式,如果所有表达式都是 null
,则返回 null
。null
,Greatest
将返回 null
。如果你知道一个合理的最小值作为默认值,可以使用 Coalesce
来模拟 PostgreSQL 的行为。
JSONObject
¶JSONObject
(**fields)¶Takes a list of key-value pairs and returns a JSON object containing those pairs.
Usage example:
>>> from django.db.models import F
>>> from django.db.models.functions import JSONObject, Lower
>>> Author.objects.create(name="Margaret Smith", alias="msmith", age=25)
>>> author = Author.objects.annotate(
... json_object=JSONObject(
... name=Lower("name"),
... alias="alias",
... age=F("age") * 2,
... )
... ).get()
>>> author.json_object
{'name': 'margaret smith', 'alias': 'msmith', 'age': 50}
Least
¶Least
(*expressions, **extra)¶接受至少两个字段名或表达式的列表,并返回最小值。每个参数必须是同样的类型,因此混合文本和数字将导致数据库错误。
警告
当一个或多个表达式可能是 null
时,Least
的行为在不同的数据库之间有所不同。
Least
将返回最小的非空表达式,如果所有表达式都是 null
,则返回 null
。null
,Least
将返回 null
。如果你知道一个合理的最大值作为默认值,可以使用` Coalesce` 来模拟 PostgreSQL 的行为。
我们将在每个函数的例子中使用以下模型:
class Experiment(models.Model):
start_datetime = models.DateTimeField()
start_date = models.DateField(null=True, blank=True)
start_time = models.TimeField(null=True, blank=True)
end_datetime = models.DateTimeField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
end_time = models.TimeField(null=True, blank=True)
Extract
¶Extract
(expression, lookup_name=None, tzinfo=None, **extra)¶提取日期的一个组成部分作为一个数字。
Takes an expression
representing a DateField
, DateTimeField
,
TimeField
, or DurationField
and a lookup_name
, and returns the part
of the date referenced by lookup_name
as an IntegerField
.
Django usually uses the databases' extract function, so you may use any
lookup_name
that your database supports. A tzinfo
subclass, usually
provided by zoneinfo
, can be passed to extract a value in a specific
timezone.
给定日期时间 2015-06-15 23:30:01.000321+00:00
,内置的 lookup_name
返回。
如果在 Django 中使用了不同的时区,比如 Australia/Melbourne
,那么在提取值之前,日期时间会被转换为该时区。在上面的例子中,墨尔本的时区偏移是 +10:00。当这个时区被激活时,返回的值将与上述相同,除了:
week_day
值
week_day
lookup_type
的计算方式与大多数数据库和 Python 的标准函数不同。这个函数将返回星期日的 1
,星期一的 2
,到星期六的 7
。
The equivalent calculation in Python is:
>>> from datetime import datetime
>>> dt = datetime(2015, 6, 15)
>>> (dt.isoweekday() % 7) + 1
2
week
值
The week
lookup_type
is calculated based on ISO-8601, i.e.,
a week starts on a Monday. The first week of a year is the one that
contains the year's first Thursday, i.e. the first week has the majority
(four or more) of its days in the year. The value returned is in the range
1 to 52 or 53.
上面的每个 lookup_name
都有一个相应的 Extract
子类(下面列出的),通常应该用这个子类来代替比较啰嗦的等价物,例如,使用 ExtractYear(...)
而不是 Extract(...,lookup_name='year')
。
Usage example:
>>> from datetime import datetime
>>> from django.db.models.functions import Extract
>>> start = datetime(2015, 6, 15)
>>> end = datetime(2015, 7, 2)
>>> Experiment.objects.create(
... start_datetime=start, start_date=start.date(), end_datetime=end, end_date=end.date()
... )
>>> # Add the experiment start year as a field in the QuerySet.
>>> experiment = Experiment.objects.annotate(
... start_year=Extract("start_datetime", "year")
... ).get()
>>> experiment.start_year
2015
>>> # How many experiments completed in the same year in which they started?
>>> Experiment.objects.filter(start_datetime__year=Extract("end_datetime", "year")).count()
1
DateField
提取¶ExtractYear
(expression, tzinfo=None, **extra)¶lookup_name = 'year'
ExtractIsoYear
(expression, tzinfo=None, **extra)¶返回 ISO-8601 的周号年份。
lookup_name = 'iso_year'
ExtractMonth
(expression, tzinfo=None, **extra)¶lookup_name = 'month'
ExtractDay
(expression, tzinfo=None, **extra)¶lookup_name = 'day'
ExtractWeekDay
(expression, tzinfo=None, **extra)¶lookup_name = 'week_day'
ExtractIsoWeekDay
(expression, tzinfo=None, **extra)¶返回 ISO-8601 的星期日,第 1 天是星期一,第 7 天是星期天。
lookup_name = 'iso_week_day'
ExtractWeek
(expression, tzinfo=None, **extra)¶lookup_name = 'week'
ExtractQuarter
(expression, tzinfo=None, **extra)¶lookup_name = 'quarter'
这些类在逻辑上等同于 Extract('date_field', lookup_name)
。每个类也是一个 Transform
在 DateField
和 DateTimeField
上注册为 __(lookup_name)`
,例如 __year
。
Since DateField
s don't have a time component, only Extract
subclasses
that deal with date-parts can be used with DateField
:
>>> from datetime import datetime, timezone
>>> from django.db.models.functions import (
... ExtractDay,
... ExtractMonth,
... ExtractQuarter,
... ExtractWeek,
... ExtractIsoWeekDay,
... ExtractWeekDay,
... ExtractIsoYear,
... ExtractYear,
... )
>>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
>>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
>>> Experiment.objects.create(
... start_datetime=start_2015,
... start_date=start_2015.date(),
... end_datetime=end_2015,
... end_date=end_2015.date(),
... )
>>> Experiment.objects.annotate(
... year=ExtractYear("start_date"),
... isoyear=ExtractIsoYear("start_date"),
... quarter=ExtractQuarter("start_date"),
... month=ExtractMonth("start_date"),
... week=ExtractWeek("start_date"),
... day=ExtractDay("start_date"),
... weekday=ExtractWeekDay("start_date"),
... isoweekday=ExtractIsoWeekDay("start_date"),
... ).values(
... "year",
... "isoyear",
... "quarter",
... "month",
... "week",
... "day",
... "weekday",
... "isoweekday",
... ).get(
... end_date__year=ExtractYear("start_date")
... )
{'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
'day': 15, 'weekday': 2, 'isoweekday': 1}
DateTimeField
提取¶除以下内容外,上述 DateField
的所有提取物也可用于``DateTimeField``。
ExtractHour
(expression, tzinfo=None, **extra)¶lookup_name = 'hour'
ExtractMinute
(expression, tzinfo=None, **extra)¶lookup_name = 'minute'
ExtractSecond
(expression, tzinfo=None, **extra)¶lookup_name = 'second'
这些类在逻辑上等同于 Extract('datetime_field', lookup_name)
。每个类也是一个 Transform
在 DateTimeField
上注册为 __(lookup_name)
,例如 __minute
。
DateTimeField
examples:
>>> from datetime import datetime, timezone
>>> from django.db.models.functions import (
... ExtractDay,
... ExtractHour,
... ExtractMinute,
... ExtractMonth,
... ExtractQuarter,
... ExtractSecond,
... ExtractWeek,
... ExtractIsoWeekDay,
... ExtractWeekDay,
... ExtractIsoYear,
... ExtractYear,
... )
>>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
>>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
>>> Experiment.objects.create(
... start_datetime=start_2015,
... start_date=start_2015.date(),
... end_datetime=end_2015,
... end_date=end_2015.date(),
... )
>>> Experiment.objects.annotate(
... year=ExtractYear("start_datetime"),
... isoyear=ExtractIsoYear("start_datetime"),
... quarter=ExtractQuarter("start_datetime"),
... month=ExtractMonth("start_datetime"),
... week=ExtractWeek("start_datetime"),
... day=ExtractDay("start_datetime"),
... weekday=ExtractWeekDay("start_datetime"),
... isoweekday=ExtractIsoWeekDay("start_datetime"),
... hour=ExtractHour("start_datetime"),
... minute=ExtractMinute("start_datetime"),
... second=ExtractSecond("start_datetime"),
... ).values(
... "year",
... "isoyear",
... "month",
... "week",
... "day",
... "weekday",
... "isoweekday",
... "hour",
... "minute",
... "second",
... ).get(
... end_datetime__year=ExtractYear("start_datetime")
... )
{'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
'day': 15, 'weekday': 2, 'isoweekday': 1, 'hour': 23, 'minute': 30,
'second': 1}
When USE_TZ
is True
then datetimes are stored in the database
in UTC. If a different timezone is active in Django, the datetime is converted
to that timezone before the value is extracted. The example below converts to
the Melbourne timezone (UTC +10:00), which changes the day, weekday, and hour
values that are returned:
>>> from django.utils import timezone
>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne") # UTC+10:00
>>> with timezone.override(melb):
... Experiment.objects.annotate(
... day=ExtractDay("start_datetime"),
... weekday=ExtractWeekDay("start_datetime"),
... isoweekday=ExtractIsoWeekDay("start_datetime"),
... hour=ExtractHour("start_datetime"),
... ).values("day", "weekday", "isoweekday", "hour").get(
... end_datetime__year=ExtractYear("start_datetime"),
... )
...
{'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}
Explicitly passing the timezone to the Extract
function behaves in the same
way, and takes priority over an active timezone:
>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> Experiment.objects.annotate(
... day=ExtractDay("start_datetime", tzinfo=melb),
... weekday=ExtractWeekDay("start_datetime", tzinfo=melb),
... isoweekday=ExtractIsoWeekDay("start_datetime", tzinfo=melb),
... hour=ExtractHour("start_datetime", tzinfo=melb),
... ).values("day", "weekday", "isoweekday", "hour").get(
... end_datetime__year=ExtractYear("start_datetime"),
... )
{'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}
Now
¶Now
¶返回数据库服务器执行查询时的当前日期和时间,通常使用 SQL CURRENT_TIMESTAMP
。
Usage example:
>>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now())
<QuerySet [<Article: How to Django>]>
PostgreSQL 的注意事项
在 PostgreSQL 中,SQL CURRENT_TIMESTAMP
返回的是当前事务开始的时间,因此为了跨数据库的兼容性,Now()
使用 STATEMENT_TIMESTAMP
代替。因此为了跨数据库的兼容性,Now()
使用 STATEMENT_TIMESTAMP
代替。如果需要事务时间戳,可以使用 django.contrib.postgres.function.TransactionNow
。
Oracle
On Oracle, the SQL LOCALTIMESTAMP
is used to avoid issues with casting
CURRENT_TIMESTAMP
to DateTimeField
.
Support for microsecond precision on MySQL and millisecond precision on SQLite were added.
In older versions, the SQL CURRENT_TIMESTAMP
was used on Oracle instead
of LOCALTIMESTAMP
.
Trunc
¶Trunc
(expression, kind, output_field=None, tzinfo=None, **extra)¶将一个日期截断到一个重要的部分。
当你只关心某事是否发生在某年、某小时或某天,而不关心确切的秒数时,那么 Trunc
(及其子类)可以用来过滤或汇总你的数据。例如,你可以使用 Trunc
来计算每天的销售数量。
Trunc
takes a single expression
, representing a DateField
,
TimeField
, or DateTimeField
, a kind
representing a date or time
part, and an output_field
that's either DateTimeField()
,
TimeField()
, or DateField()
. It returns a datetime, date, or time
depending on output_field
, with fields up to kind
set to their minimum
value. If output_field
is omitted, it will default to the output_field
of expression
. A tzinfo
subclass, usually provided by zoneinfo
,
can be passed to truncate a value in a specific timezone.
给定日期时间 2015-06-15 14:30:50.000321+00:00
,内置 kind
返回:
如果在 Django 中使用了不同的时区,比如 Australia/Melbourne
,那么日期时间会在被截断之前转换为新的时区。在上面的例子中,墨尔本的时区偏移是 +10:00。当这个时区被激活时,返回的值将是:
年的偏移量为 +11:00,因为结果过渡到夏令时。
以上每个 kind
都有一个对应的 Trunc
子类(下面列出的),通常应该用这个子类来代替比较啰嗦的等价物,例如使用 TruncYear(...)
而不是 Trunc(...,kind='year')
。
子类都被定义为变换,但它们没有注册任何字段,因为查找名称已经被 Extract
子类保留。
Usage example:
>>> from datetime import datetime
>>> from django.db.models import Count, DateTimeField
>>> from django.db.models.functions import Trunc
>>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 30, 50, 321))
>>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 40, 2, 123))
>>> Experiment.objects.create(start_datetime=datetime(2015, 12, 25, 10, 5, 27, 999))
>>> experiments_per_day = (
... Experiment.objects.annotate(
... start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
... )
... .values("start_day")
... .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_day:
... print(exp["start_day"], exp["experiments"])
...
2015-06-15 00:00:00 2
2015-12-25 00:00:00 1
>>> experiments = Experiment.objects.annotate(
... start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
... ).filter(start_day=datetime(2015, 6, 15))
>>> for exp in experiments:
... print(exp.start_datetime)
...
2015-06-15 14:30:50.000321
2015-06-15 14:40:02.000123
DateField
截断¶TruncYear
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'year'
TruncMonth
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'month'
TruncWeek
(expression, output_field=None, tzinfo=None, **extra)¶截断到每周一的午夜。
kind = 'week'
TruncQuarter
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'quarter'
这些在逻辑上等同于 Trunc('date_field', kind)
。它们截断日期的所有部分,直至 kind
,允许以较低的精度对日期进行分组或过滤。expression
可以有一个 output_field
的 DateField
或 DateTimeField
。
Since DateField
s don't have a time component, only Trunc
subclasses
that deal with date-parts can be used with DateField
:
>>> from datetime import datetime, timezone
>>> from django.db.models import Count
>>> from django.db.models.functions import TruncMonth, TruncYear
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
>>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.utc)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> Experiment.objects.create(start_datetime=start2, start_date=start2.date())
>>> Experiment.objects.create(start_datetime=start3, start_date=start3.date())
>>> experiments_per_year = (
... Experiment.objects.annotate(year=TruncYear("start_date"))
... .values("year")
... .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_year:
... print(exp["year"], exp["experiments"])
...
2014-01-01 1
2015-01-01 2
>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> experiments_per_month = (
... Experiment.objects.annotate(month=TruncMonth("start_datetime", tzinfo=melb))
... .values("month")
... .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_month:
... print(exp["month"], exp["experiments"])
...
2015-06-01 00:00:00+10:00 1
2016-01-01 00:00:00+11:00 1
2014-06-01 00:00:00+10:00 1
DateTimeField
截断¶TruncDate
(expression, tzinfo=None, **extra)¶lookup_name = 'date'
output_field = DateField()
TruncDate
将 expression
投射到一个日期,而不是使用内置的 SQL truncate 函数。在 DateTimeField
上,它也被注册为 __date
的转换。
TruncTime
(expression, tzinfo=None, **extra)¶lookup_name = 'time'
output_field = TimeField()
TruncTime
将 expression
投射到一个时间,而不是使用内置的 SQL truncate 函数。在 DateTimeField
上,它也被注册为 __time
的转换。
TruncDay
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'day'
TruncHour
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'hour'
TruncMinute
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'minute'
TruncSecond
(expression, output_field=None, tzinfo=None, **extra)¶kind = 'second'
这些在逻辑上等同于 Trunc('datetime_field', kind)
。它们截断日期的所有部分,直至 kind
,并允许以较低的精度对日期时间进行分组或过滤。expression
必须有一个 output_field
的 DateTimeField
。
Usage example:
>>> from datetime import date, datetime, timezone
>>> from django.db.models import Count
>>> from django.db.models.functions import (
... TruncDate,
... TruncDay,
... TruncHour,
... TruncMinute,
... TruncSecond,
... )
>>> import zoneinfo
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> Experiment.objects.annotate(
... date=TruncDate("start_datetime"),
... day=TruncDay("start_datetime", tzinfo=melb),
... hour=TruncHour("start_datetime", tzinfo=melb),
... minute=TruncMinute("start_datetime"),
... second=TruncSecond("start_datetime"),
... ).values("date", "day", "hour", "minute", "second").get()
{'date': datetime.date(2014, 6, 15),
'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=timezone.utc),
'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=timezone.utc)
}
TimeField
截断¶TruncHour
(expression, output_field=None, tzinfo=None, **extra)kind = 'hour'
TruncMinute
(expression, output_field=None, tzinfo=None, **extra)kind = 'minute'
TruncSecond
(expression, output_field=None, tzinfo=None, **extra)kind = 'second'
这些在逻辑上等同于 Trunc('time_field', kind)
。它们截断时间的所有部分,直至 kind
,这就允许以较低的精度对时间进行分组或过滤。expression
可以有一个 output_field
的 TimeField
或 DateTimeField
。
Since TimeField
s don't have a date component, only Trunc
subclasses
that deal with time-parts can be used with TimeField
:
>>> from datetime import datetime, timezone
>>> from django.db.models import Count, TimeField
>>> from django.db.models.functions import TruncHour
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> start2 = datetime(2014, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
>>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.utc)
>>> Experiment.objects.create(start_datetime=start1, start_time=start1.time())
>>> Experiment.objects.create(start_datetime=start2, start_time=start2.time())
>>> Experiment.objects.create(start_datetime=start3, start_time=start3.time())
>>> experiments_per_hour = (
... Experiment.objects.annotate(
... hour=TruncHour("start_datetime", output_field=TimeField()),
... )
... .values("hour")
... .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_hour:
... print(exp["hour"], exp["experiments"])
...
14:00:00 2
17:00:00 1
>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> experiments_per_hour = (
... Experiment.objects.annotate(
... hour=TruncHour("start_datetime", tzinfo=melb),
... )
... .values("hour")
... .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_hour:
... print(exp["hour"], exp["experiments"])
...
2014-06-16 00:00:00+10:00 2
2016-01-01 04:00:00+11:00 1
我们将在数学函数实例中使用以下模型:
class Vector(models.Model):
x = models.FloatField()
y = models.FloatField()
Abs
¶Abs
(expression, **extra)¶返回一个数值字段或表达式的绝对值。
Usage example:
>>> from django.db.models.functions import Abs
>>> Vector.objects.create(x=-0.5, y=1.1)
>>> vector = Vector.objects.annotate(x_abs=Abs("x"), y_abs=Abs("y")).get()
>>> vector.x_abs, vector.y_abs
(0.5, 1.1)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Abs
>>> FloatField.register_lookup(Abs)
>>> # Get vectors inside the unit cube
>>> vectors = Vector.objects.filter(x__abs__lt=1, y__abs__lt=1)
ACos
¶ACos
(expression, **extra)¶返回一个数值字段或表达式的余弦值。表达式的值必须在 -1 到 1 的范围内。
Usage example:
>>> from django.db.models.functions import ACos
>>> Vector.objects.create(x=0.5, y=-0.9)
>>> vector = Vector.objects.annotate(x_acos=ACos("x"), y_acos=ACos("y")).get()
>>> vector.x_acos, vector.y_acos
(1.0471975511965979, 2.6905658417935308)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import ACos
>>> FloatField.register_lookup(ACos)
>>> # Get vectors whose arccosine is less than 1
>>> vectors = Vector.objects.filter(x__acos__lt=1, y__acos__lt=1)
ASin
¶ASin
(expression, **extra)¶返回一个数值字段或表达式的正弦值。表达式的值必须在 -1 到 1 的范围内。
Usage example:
>>> from django.db.models.functions import ASin
>>> Vector.objects.create(x=0, y=1)
>>> vector = Vector.objects.annotate(x_asin=ASin("x"), y_asin=ASin("y")).get()
>>> vector.x_asin, vector.y_asin
(0.0, 1.5707963267948966)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import ASin
>>> FloatField.register_lookup(ASin)
>>> # Get vectors whose arcsine is less than 1
>>> vectors = Vector.objects.filter(x__asin__lt=1, y__asin__lt=1)
ATan
¶ATan
(expression, **extra)¶返回一个数值字段或表达式的正切值。
Usage example:
>>> from django.db.models.functions import ATan
>>> Vector.objects.create(x=3.12, y=6.987)
>>> vector = Vector.objects.annotate(x_atan=ATan("x"), y_atan=ATan("y")).get()
>>> vector.x_atan, vector.y_atan
(1.2606282660069106, 1.428638798133829)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import ATan
>>> FloatField.register_lookup(ATan)
>>> # Get vectors whose arctangent is less than 2
>>> vectors = Vector.objects.filter(x__atan__lt=2, y__atan__lt=2)
ATan2
¶ATan2
(expression1, expression2, **extra)¶返回 expression1 / expression2
的正切值。
Usage example:
>>> from django.db.models.functions import ATan2
>>> Vector.objects.create(x=2.5, y=1.9)
>>> vector = Vector.objects.annotate(atan2=ATan2("x", "y")).get()
>>> vector.atan2
0.9209258773829491
Ceil
¶Ceil
(expression, **extra)¶返回大于或等于一个数值字段或表达式的最小整数。
Usage example:
>>> from django.db.models.functions import Ceil
>>> Vector.objects.create(x=3.12, y=7.0)
>>> vector = Vector.objects.annotate(x_ceil=Ceil("x"), y_ceil=Ceil("y")).get()
>>> vector.x_ceil, vector.y_ceil
(4.0, 7.0)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Ceil
>>> FloatField.register_lookup(Ceil)
>>> # Get vectors whose ceil is less than 10
>>> vectors = Vector.objects.filter(x__ceil__lt=10, y__ceil__lt=10)
Cos
¶Cos
(expression, **extra)¶返回一个数值字段或表达式的余弦值。
Usage example:
>>> from django.db.models.functions import Cos
>>> Vector.objects.create(x=-8.0, y=3.1415926)
>>> vector = Vector.objects.annotate(x_cos=Cos("x"), y_cos=Cos("y")).get()
>>> vector.x_cos, vector.y_cos
(-0.14550003380861354, -0.9999999999999986)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cos
>>> FloatField.register_lookup(Cos)
>>> # Get vectors whose cosine is less than 0.5
>>> vectors = Vector.objects.filter(x__cos__lt=0.5, y__cos__lt=0.5)
Cot
¶Cot
(expression, **extra)¶返回数值字段或表达式的正切值。
Usage example:
>>> from django.db.models.functions import Cot
>>> Vector.objects.create(x=12.0, y=1.0)
>>> vector = Vector.objects.annotate(x_cot=Cot("x"), y_cot=Cot("y")).get()
>>> vector.x_cot, vector.y_cot
(-1.5726734063976826, 0.642092615934331)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cot
>>> FloatField.register_lookup(Cot)
>>> # Get vectors whose cotangent is less than 1
>>> vectors = Vector.objects.filter(x__cot__lt=1, y__cot__lt=1)
Degrees
¶Degrees
(expression, **extra)¶将数值字段或表达式从弧度转换为度。
Usage example:
>>> from django.db.models.functions import Degrees
>>> Vector.objects.create(x=-1.57, y=3.14)
>>> vector = Vector.objects.annotate(x_d=Degrees("x"), y_d=Degrees("y")).get()
>>> vector.x_d, vector.y_d
(-89.95437383553924, 179.9087476710785)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Degrees
>>> FloatField.register_lookup(Degrees)
>>> # Get vectors whose degrees are less than 360
>>> vectors = Vector.objects.filter(x__degrees__lt=360, y__degrees__lt=360)
Exp
¶Exp
(expression, **extra)¶返回 e
(自然对数基数)的值,将其升为一个数值字段或表达式的幂。
Usage example:
>>> from django.db.models.functions import Exp
>>> Vector.objects.create(x=5.4, y=-2.0)
>>> vector = Vector.objects.annotate(x_exp=Exp("x"), y_exp=Exp("y")).get()
>>> vector.x_exp, vector.y_exp
(221.40641620418717, 0.1353352832366127)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Exp
>>> FloatField.register_lookup(Exp)
>>> # Get vectors whose exp() is greater than 10
>>> vectors = Vector.objects.filter(x__exp__gt=10, y__exp__gt=10)
Floor
¶Floor
(expression, **extra)¶返回不大于数值字段或表达式的最大整数值。
Usage example:
>>> from django.db.models.functions import Floor
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_floor=Floor("x"), y_floor=Floor("y")).get()
>>> vector.x_floor, vector.y_floor
(5.0, -3.0)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Floor
>>> FloatField.register_lookup(Floor)
>>> # Get vectors whose floor() is greater than 10
>>> vectors = Vector.objects.filter(x__floor__gt=10, y__floor__gt=10)
Ln
¶Ln
(expression, **extra)¶返回一个数值字段或表达式的自然对数。
Usage example:
>>> from django.db.models.functions import Ln
>>> Vector.objects.create(x=5.4, y=233.0)
>>> vector = Vector.objects.annotate(x_ln=Ln("x"), y_ln=Ln("y")).get()
>>> vector.x_ln, vector.y_ln
(1.6863989535702288, 5.4510384535657)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Ln
>>> FloatField.register_lookup(Ln)
>>> # Get vectors whose value greater than e
>>> vectors = Vector.objects.filter(x__ln__gt=1, y__ln__gt=1)
Log
¶Log
(expression1, expression2, **extra)¶Accepts two numeric fields or expressions and returns the logarithm of the second to base of the first.
Usage example:
>>> from django.db.models.functions import Log
>>> Vector.objects.create(x=2.0, y=4.0)
>>> vector = Vector.objects.annotate(log=Log("x", "y")).get()
>>> vector.log
2.0
Mod
¶Mod
(expression1, expression2, **extra)¶接受两个数值字段或表达式,并返回第一个字段除以第二个字段的余数(模数运算)。
Usage example:
>>> from django.db.models.functions import Mod
>>> Vector.objects.create(x=5.4, y=2.3)
>>> vector = Vector.objects.annotate(mod=Mod("x", "y")).get()
>>> vector.mod
0.8
Power
¶Power
(expression1, expression2, **extra)¶接受两个数值字段或表达式,并将第一个字段的值提高到第二个字段的幂。
Usage example:
>>> from django.db.models.functions import Power
>>> Vector.objects.create(x=2, y=-2)
>>> vector = Vector.objects.annotate(power=Power("x", "y")).get()
>>> vector.power
0.25
Radians
¶Radians
(expression, **extra)¶将数值字段或表达式从度数转换为弧度。
Usage example:
>>> from django.db.models.functions import Radians
>>> Vector.objects.create(x=-90, y=180)
>>> vector = Vector.objects.annotate(x_r=Radians("x"), y_r=Radians("y")).get()
>>> vector.x_r, vector.y_r
(-1.5707963267948966, 3.141592653589793)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Radians
>>> FloatField.register_lookup(Radians)
>>> # Get vectors whose radians are less than 1
>>> vectors = Vector.objects.filter(x__radians__lt=1, y__radians__lt=1)
Round
¶Round
(expression, precision=0, **extra)¶Rounds a numeric field or expression to precision
(must be an integer)
decimal places. By default, it rounds to the nearest integer. Whether half
values are rounded up or down depends on the database.
Usage example:
>>> from django.db.models.functions import Round
>>> Vector.objects.create(x=5.4, y=-2.37)
>>> vector = Vector.objects.annotate(x_r=Round("x"), y_r=Round("y", precision=1)).get()
>>> vector.x_r, vector.y_r
(5.0, -2.4)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Round
>>> FloatField.register_lookup(Round)
>>> # Get vectors whose round() is less than 20
>>> vectors = Vector.objects.filter(x__round__lt=20, y__round__lt=20)
Sign
¶Sign
(expression, **extra)¶返回一个数字字段或表达式的符号(-1,0,1)。
Usage example:
>>> from django.db.models.functions import Sign
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_sign=Sign("x"), y_sign=Sign("y")).get()
>>> vector.x_sign, vector.y_sign
(1, -1)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sign
>>> FloatField.register_lookup(Sign)
>>> # Get vectors whose signs of components are less than 0.
>>> vectors = Vector.objects.filter(x__sign__lt=0, y__sign__lt=0)
Sin
¶Sin
(expression, **extra)¶返回一个数值字段或表达式的正弦值。
Usage example:
>>> from django.db.models.functions import Sin
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_sin=Sin("x"), y_sin=Sin("y")).get()
>>> vector.x_sin, vector.y_sin
(-0.7727644875559871, -0.7457052121767203)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sin
>>> FloatField.register_lookup(Sin)
>>> # Get vectors whose sin() is less than 0
>>> vectors = Vector.objects.filter(x__sin__lt=0, y__sin__lt=0)
Sqrt
¶Sqrt
(expression, **extra)¶返回一个非负数值字段或表达式的平方根。
Usage example:
>>> from django.db.models.functions import Sqrt
>>> Vector.objects.create(x=4.0, y=12.0)
>>> vector = Vector.objects.annotate(x_sqrt=Sqrt("x"), y_sqrt=Sqrt("y")).get()
>>> vector.x_sqrt, vector.y_sqrt
(2.0, 3.46410)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sqrt
>>> FloatField.register_lookup(Sqrt)
>>> # Get vectors whose sqrt() is less than 5
>>> vectors = Vector.objects.filter(x__sqrt__lt=5, y__sqrt__lt=5)
Tan
¶Tan
(expression, **extra)¶返回一个数值字段或表达式的正切值。
Usage example:
>>> from django.db.models.functions import Tan
>>> Vector.objects.create(x=0, y=12)
>>> vector = Vector.objects.annotate(x_tan=Tan("x"), y_tan=Tan("y")).get()
>>> vector.x_tan, vector.y_tan
(0.0, -0.6358599286615808)
It can also be registered as a transform. For example:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Tan
>>> FloatField.register_lookup(Tan)
>>> # Get vectors whose tangent is less than 0
>>> vectors = Vector.objects.filter(x__tan__lt=0, y__tan__lt=0)
Chr
¶Chr
(expression, **extra)¶接受一个数值字段或表达式,并将表达式的文本表示形式作为单个字符返回。它的工作原理与 Python 的 chr()
函数相同。
和 Length
一样,它也可以在 IntegerField
上作为变换注册。默认的查询名是 chr
。
Usage example:
>>> from django.db.models.functions import Chr
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.filter(name__startswith=Chr(ord("M"))).get()
>>> print(author.name)
Margaret Smith
Concat
¶Concat
(*expressions, **extra)¶接受至少两个文本字段或表达式的列表,并返回连接后的文本。每个参数必须是文本或字符类型。如果你想把一个 TextField()
和一个 CharField()
连接起来,那么一定要告诉 Django,output_field
应该是一个 TextField()
。当连接一个 Value
时,也需要指定一个 output_field
,如下面的例子。
这个函数永远不会有一个空的结果。在后端,如果一个空参数导致整个表达式为空,Django 会确保每个空的部分先转换成空字符串。
Usage example:
>>> # Get the display name as "name (goes_by)"
>>> from django.db.models import CharField, Value as V
>>> from django.db.models.functions import Concat
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(
... screen_name=Concat("name", V(" ("), "goes_by", V(")"), output_field=CharField())
... ).get()
>>> print(author.screen_name)
Margaret Smith (Maggie)
Left
¶Left
(expression, length, **extra)¶返回给定文本字段或表达式的第一个 length
字符。
Usage example:
>>> from django.db.models.functions import Left
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(first_initial=Left("name", 1)).get()
>>> print(author.first_initial)
M
Length
¶Length
(expression, **extra)¶接受单个文本字段或表达式,并返回值的字符数。如果表达式为空,则长度也为空。
Usage example:
>>> # Get the length of the name and goes_by fields
>>> from django.db.models.functions import Length
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(
... name_length=Length("name"), goes_by_length=Length("goes_by")
... ).get()
>>> print(author.name_length, author.goes_by_length)
(14, None)
It can also be registered as a transform. For example:
>>> from django.db.models import CharField
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length)
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)
Lower
¶Lower
(expression, **extra)¶接受单个文本字段或表达式,并返回小写表示。
它也可以像 Length
中描述的那样,作为一个变换注册。
Usage example:
>>> from django.db.models.functions import Lower
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_lower=Lower("name")).get()
>>> print(author.name_lower)
margaret smith
LPad
¶LPad
(expression, length, fill_text=Value(' '), **extra)¶返回给定的文本字段或表达式的值,在左侧用 fill_text
填充,使结果是 length
字符长。默认的 fill_text
是一个空格。
Usage example:
>>> from django.db.models import Value
>>> from django.db.models.functions import LPad
>>> Author.objects.create(name="John", alias="j")
>>> Author.objects.update(name=LPad("name", 8, Value("abc")))
1
>>> print(Author.objects.get(alias="j").name)
abcaJohn
MD5
¶MD5
(expression, **extra)¶接受单个文本字段或表达式,并返回字符串的 MD5 哈希值。
它也可以像 Length
中描述的那样,作为一个变换注册。
Usage example:
>>> from django.db.models.functions import MD5
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_md5=MD5("name")).get()
>>> print(author.name_md5)
749fb689816b2db85f5b169c2055b247
Ord
¶Ord
(expression, **extra)¶接受一个文本字段或表达式,并返回该表达式第一个字符的 Unicode 码点值。它的工作原理类似于 Python 的 ord()
函数,但如果表达式超过一个字符,则不会引发异常。
也可以像 Length
中描述的那样,把它注册为一个变换。默认的查找名称是 ord
。
Usage example:
>>> from django.db.models.functions import Ord
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_code_point=Ord("name")).get()
>>> print(author.name_code_point)
77
Repeat
¶Repeat
(expression, number, **extra)¶返回给定文本字段或表达式重复 number
次数的值。
Usage example:
>>> from django.db.models.functions import Repeat
>>> Author.objects.create(name="John", alias="j")
>>> Author.objects.update(name=Repeat("name", 3))
1
>>> print(Author.objects.get(alias="j").name)
JohnJohnJohn
Replace
¶Replace
(expression, text, replacement=Value(''), **extra)¶在 expression
中用 replacement
替换所有出现的 text
。默认替换文本是空字符串。函数的参数是区分大小写的。
Usage example:
>>> from django.db.models import Value
>>> from django.db.models.functions import Replace
>>> Author.objects.create(name="Margaret Johnson")
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.update(name=Replace("name", Value("Margaret"), Value("Margareth")))
2
>>> Author.objects.values("name")
<QuerySet [{'name': 'Margareth Johnson'}, {'name': 'Margareth Smith'}]>
Reverse
¶Reverse
(expression, **extra)¶接受单个文本字段或表达式,并将该表达式的字符按相反顺序返回。
也可以像 Length
中描述的那样,把它注册为一个变换。默认的查询名称是 reverse
。
Usage example:
>>> from django.db.models.functions import Reverse
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(backward=Reverse("name")).get()
>>> print(author.backward)
htimS teragraM
Right
¶Right
(expression, length, **extra)¶返回给定文本字段或表达式的最后 length
字符。
Usage example:
>>> from django.db.models.functions import Right
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(last_letter=Right("name", 1)).get()
>>> print(author.last_letter)
h
SHA1
、SHA224`、SHA256`、SHA384` 和 SHA512
。¶SHA1
(expression, **extra)¶SHA224
(expression, **extra)¶SHA256
(expression, **extra)¶SHA384
(expression, **extra)¶SHA512
(expression, **extra)¶接受单个文本字段或表达式,并返回字符串的特定哈希值。
它们也可以像 Length
中描述的那样注册为变换。
Usage example:
>>> from django.db.models.functions import SHA1
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_sha1=SHA1("name")).get()
>>> print(author.name_sha1)
b87efd8a6c991c390be5a68e8a7945a7851c7e5c
PostgreSQL
必须安装 pgcrypto 扩展 。你可以使用 CryptoExtension
迁移操作来安装它。
Oracle
Oracle 不支持 SHA224
函数。
StrIndex
¶StrIndex
(string, substring, **extra)¶返回一个正整数,对应于 string
中第一次出现的 substring
的 1 个索引位置,如果没有找到 substring
,则返回 0。
Usage example:
>>> from django.db.models import Value as V
>>> from django.db.models.functions import StrIndex
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.create(name="Smith, Margaret")
>>> Author.objects.create(name="Margaret Jackson")
>>> Author.objects.filter(name="Margaret Jackson").annotate(
... smith_index=StrIndex("name", V("Smith"))
... ).get().smith_index
0
>>> authors = Author.objects.annotate(smith_index=StrIndex("name", V("Smith"))).filter(
... smith_index__gt=0
... )
<QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>
警告
在 MySQL 中,数据库表的 字符序 决定了字符串比较(如本函数的 expression
和 substring
)是否区分大小写。默认情况下,比较是不区分大小写的。
Substr
¶Substr
(expression, pos, length=None, **extra)¶从字段或表达式的位置 pos
开始返回一个长度为 length
的子串。如果 length
是 None
,那么将返回字符串的其余部分。
Usage example:
>>> # Set the alias to the first 5 characters of the name as lowercase
>>> from django.db.models.functions import Lower, Substr
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.update(alias=Lower(Substr("name", 1, 5)))
1
>>> print(Author.objects.get(name="Margaret Smith").alias)
marga
Trim
¶Trim
(expression, **extra)¶返回给定的文本字段或表达式的值,并去除前导和尾部的空格。
Usage example:
>>> from django.db.models.functions import Trim
>>> Author.objects.create(name=" John ", alias="j")
>>> Author.objects.update(name=Trim("name"))
1
>>> print(Author.objects.get(alias="j").name)
John
Upper
¶Upper
(expression, **extra)¶接受单个文本字段或表达式,并返回大写表示。
它也可以像 Length
中描述的那样,作为一个变换注册。
Usage example:
>>> from django.db.models.functions import Upper
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_upper=Upper("name")).get()
>>> print(author.name_upper)
MARGARET SMITH
在 Window
表达式中,有很多函数可以用来计算元素的等级或某些行的 Ntile
。
Lag
¶Lag
(expression, offset=1, default=None, **extra)¶计算 offset
的偏移值,如果没有行存在,返回 default
。
default
必须与 expression
具有相同的类型,但是,这只由数据库验证,而不是在 Python 中验证。
MariaDB 和 default
MariaDB 不支持 这个 default
参数。
Lead
¶Lead
(expression, offset=1, default=None, **extra)¶计算给定 frame 中的前导值。offset
和 default
都是根据当前行的情况来计算的。
default
必须与 expression
具有相同的类型,但是,这只由数据库验证,而不是在 Python 中验证。
MariaDB 和 default
MariaDB 不支持 这个 default
参数。
NthValue
¶NthValue
(expression, nth=1, **extra)¶计算相对于窗口内偏移量 nth
(必须是正值)的行。如果没有行,返回 None
。
一些数据库可能会以不同的方式处理不存在的 nth-value,例如,对于基于字符的表达式,Oracle 会返回一个空字符串,而不是 None
。在这些情况下,Django 不做任何转换。
Ntile
¶Ntile
(num_buckets=1, **extra)¶为帧子句中的每一行计算一个分区,在 1 和 num_buckets
之间尽可能均匀地分配数字。如果行没有被平均分配到若干个桶中,则一个或多个桶将被更频繁地表示。
PercentRank
¶PercentRank
(*expressions, **extra)¶Computes the relative rank of the rows in the frame clause. This computation is equivalent to evaluating:
(rank - 1) / (total rows - 1)
The following table explains the calculation for the relative rank of a row:
行 # | 值 | 排名 | 计算 | Relative Rank |
---|---|---|---|---|
1 | 15 | 1 | (1-1)/(7-1) | 0.0000 |
2 | 20 | 2 | (2-1)/(7-1) | 0.1666 |
3 | 20 | 2 | (2-1)/(7-1) | 0.1666 |
4 | 20 | 2 | (2-1)/(7-1) | 0.1666 |
5 | 30 | 5 | (5-1)/(7-1) | 0.6666 |
6 | 30 | 5 | (5-1)/(7-1) | 0.6666 |
7 | 40 | 7 | (7-1)/(7-1) | 1.0000 |
12月 05, 2023