データベース関数¶
以下で説明するクラスは、基盤となるデータベースが提供する関数を、ユーザが Django のアノテーション、集計、フィルタとして使う方法を提供します。関数は 式 (expression) でもあるので、 集計関数 のように他の式と組み合わせて使うこともできます。
各関数の例では、以下のモデルを使用します:
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)
通常、CharField
に null=True
を許可することはお勧めしません。なぜなら、これはフィールドに2つの "空の値 "を持たせてしまうからです。
比較および変換関数¶
Cast
¶
式 expression
の結果の型を output_field
の型に強制的に変更します。
使用例:
>>> 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
¶
少なくとも2つのフィールド名または式のリストを受け取り、最初のNULLでない値を返します(空文字列はNULL値とはみなされないことに注意してください)。各引数は同じような型でなければならないので、テキストと数値が混在するとデータベースエラーになります。
使用例:
>>> # 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
¶
クエリに使用する式と照合順序名 (collation name) を指定します。
たとえば、SQLiteで大文字小文字を区別せずにフィルタリングする場合、以下のようにします:
>>> Author.objects.filter(name=Collate(Value("john"), "nocase"))
<QuerySet [<Author: John>, <Author: john>]>
また、PostgreSQLなどでのソートにも使用できます:
>>> Author.objects.order_by(Collate("name", "et-x-icu"))
<QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>
Greatest
¶
少なくとも2つのフィールド名または式のリストを受け取り、最大値を返します。各引数は同じような型でなければならないので、テキストと数値が混在するとデータベースエラーになります。
使用例:
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
のうち最新のものになります。
警告
1つ以上の式が null
である場合の Greatest
の動作はデータベースによって異なります:
PostgreSQL:
Greatest
は、非nullの式の中で最大のものを返します。すべての式がnull
の場合はnull
を返します。SQLite, Oracle, MySQL: いずれかの式が
null
である場合、Greatest
はnull
を返します。
PostgreSQLの動作は、デフォルトとして提供する適切な最小値を知っていれば、 Coalesce
を使用してエミュレートできます。
JSONObject
¶
キーと値のペアのリストを受け取り、それらのペアを含むJSONオブジェクトを返します。
使用例:
>>> 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
¶
少なくとも2つのフィールド名または式のリストを受け取り、最小の値を返します。各引数は同じような型でなければならないので、テキストと数値が混在するとデータベースエラーになります。
警告
1つ以上の式が null
である場合の Least
の動作はデータベースによって異なります:
PostgreSQL:
Least
は、非nullの式の中で最小のものを返します。すべての式がnull
の場合はnull
を返します。SQLite, Oracle, MySQL: いずれかの式が
null
である場合、Least
はnull
を返します。
PostgreSQLの動作は、デフォルトとして提供する適切な最大値を知っていれば、 Coalesce
を使用してエミュレートできます。
NullIf
¶
2つの式を受け取り、等しい場合は None
を返し、そうでない場合は expression1
を返します。
Oracle に関する注意事項
Oracle の慣習 により、 CharField
型の式の場合、この関数は None
の代わりに空の文字列を返します。
Oracle では最初の引数として NULL
を受け付けないため、expression1
に Value(None)
を渡すことは禁止されています。
日時関連の関数¶
各関数の例では、以下のモデルを使用します:
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
¶
日時の構成要素を数値として取り出します。
DateField
, DateTimeField
, TimeField
または DurationField
を表す expression
と、lookup_name
を受け取り、 lookup_name
が参照する日付の部分を IntegerField
として返します。Django は通常データベースの extract 関数を使うので、データベースがサポートしている lookup_name
を使うことができます。通常 zoneinfo
によって提供される tzinfo
サブクラスを渡すと、特定のタイムゾーンの値を抽出できます。
datetime 2015-06-15 23:30:01.000321+00:00
が渡されると、組み込みの lookup_name
は下記の値を返します:
"year": 2015
"iso_year": 2015
"quarter": 2
"month": 6
"day": 15
"week": 25
"week_day": 2
"iso_week_day": 1
"hour": 23
"minute": 30
"second": 1
Australia/Melbourne
のような異なるタイムゾーンが Django で有効な場合、 datetime は値を抽出する前にそのタイムゾーンに変換されます。上の例の日付のメルボルンのタイムゾーンオフセットは +10:00 です。このタイムゾーンが有効な場合に返される値は、以下を除けば上と同じです:
"day": 16
"week_day": 3
"iso_week_day": 2
"hour": 9
week_day
の値
week_day
lookup_type
は、多くのデータベースや Python の標準関数とは異なる方法で計算されます。この関数は日曜日に 1
、月曜日に 2
、土曜日に 7
を返します。
Pythonでの等価な計算は以下のようになります:
>>> from datetime import datetime
>>> dt = datetime(2015, 6, 15)
>>> (dt.isoweekday() % 7) + 1
2
week
の値
week
の lookup_type
は ISO-8601 に基づいて計算されます。つまり、週は月曜日に始まります。年の最初の週は、その年の最初の木曜日を含む週です。つまり、最初の週はその週の日数の過半数(4日以上)がその年に含まれています。返される値は1から52または53の範囲です。
各 lookup_name
には、冗長な等価表現の代わりに通常使用すべき Extract
サブクラス(下記)があります。たとえば Extract(..., lookup_name='year')
の代わりに ExtractYear(...)
が使えます。
使用例:
>>> 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
からの抽出 (extract)¶
- class ExtractIsoYear(expression, tzinfo=None, **extra)[ソース]¶
ISO-8601 の週番号を持つ年を返します。
- lookup_name = 'iso_year'
- class ExtractIsoWeekDay(expression, tzinfo=None, **extra)[ソース]¶
ISO-8601形式の曜日を返します。1が月曜日で7が日曜日になります。
- lookup_name = 'iso_week_day'
これらは論理的には Extract('date_field', lookup_name)
と等価です。各クラスは DateField
と DateTimeField
に __(lookup_name)
として登録された Transform
でもあります。たとえば __year
のようなものです。
DateField
は時間要素を持たないので、日付部分を扱う Extract
サブクラスだけが 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
からの抽出 (extract)¶
以下に加え、上記の DateField
のすべての抽出操作 (extract) は DateTimeField
にも使用できます。
これらは論理的には Extract('datetime_field', lookup_name)
と等価です。各クラスは DateTimeField
に __(lookup_name)
として登録された Transform
でもあります。たとえば、 __minute
のようなものです。
DateTimeField
の例:
>>> 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}
USE_TZ
が True
の場合、 datetime は UTC でデータベースに保存されます。異なるタイムゾーンが Django で有効な場合、 datetime はそのタイムゾーンに変換されてから値が抽出されます。以下の例では、メルボルンのタイムゾーン (UTC +10:00) に変換しています。これにより、返される日、曜日、時間の値が変わります:
>>> 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}
明示的にタイムゾーンを Extract
関数に渡しても同じように動作し、アクティブなタイムゾーンよりも優先されます:
>>> 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
¶
クエリが実行された時のデータベースサーバの現在の日時を返します。通常は CURRENT_TIMESTAMP
という SQL を使用します。
使用例:
>>> 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
を使用します。トランザクションのタイムスタンプが必要な場合は、 django.contrib.postgres.functions.TransactionNow
を使用してください。
Oracle
Oracle では、CURRENT_TIMESTAMP
を DateTimeField
にキャストする際の問題を回避するために LOCALTIMESTAMP
という SQL が使用されます。
古いバージョンでは、Oracle上で LOCALTIMESTAMP
の代わりに CURRENT_TIMESTAMP
SQL構文が使用されていました。
Trunc
¶
日付を重要な要素まで切り捨てます。
特定の年、時間、日に何かが起こったかどうかだけを気にしていて、正確な秒は気にしていない場合、Trunc
(とそのサブクラス) はデータのフィルタや集計に便利です。例えば、 Trunc
を使って一日の売上数を計算できます。
Trunc
は (DateField
, TimeField
, または DateTimeField
を表す) 単一の expression
、日付または時刻の部分を表す kind
、そして (DateTimeField()
, TimeField()
, または DateField()
のいずれかである) output_field
を受け取ります。これは output_field
に応じて日時、日付、または時刻を返し、kind
単位未満のフィールドをその最小値に設定します。output_field
が省略された場合、デフォルトで expression
の output_field
になります。特定のタイムゾーンで値を切り捨てるために、通常 zoneinfo
によって提供される tzinfo
サブクラスを渡すことができます。
datetime 2015-06-15 14:30:50.000321+00:00
が渡された場合、組み込みの kind
は以下の値を返します:
"year": 2015-01-01 00:00:00+00:00
"quarter": 2015-04-01 00:00:00+00:00
"month": 2015-06-01 00:00:00+00:00
"week": 2015-06-15 00:00:00+00:00
"day": 2015-06-15 00:00:00+00:00
"hour": 2015-06-15 14:00:00+00:00
"minute": 2015-06-15 14:30:00+00:00
"second": 2015-06-15 14:30:50+00:00
Australia/Melbourne
のような異なるタイムゾーンが Django で有効な場合、 datetime は切り捨てられる前に新しいタイムゾーンに変換されます。上の例の日付のメルボルンのタイムゾーンオフセットは +10:00 です。このタイムゾーンが有効な場合に返される値は以下のようになります:
"year": 2015-01-01 00:00:00+11:00
"quarter": 2015-04-01 00:00:00+10:00
"month": 2015-06-01 00:00:00+10:00
"week": 2015-06-16 00:00:00+10:00
"day": 2015-06-16 00:00:00+10:00
"hour": 2015-06-16 00:00:00+10:00
"minute": 2015-06-16 00:30:00+10:00
"second": 2015-06-16 00:30:50+10:00
この年はサマータイムに移行したため、+11:00のオフセットがあります。
各 kind
には、冗長な等価表現の代わりに通常使用すべき Trunc
サブクラス(下記)があります。たとえば Trunc(..., kind='year')
の代わりに TruncYear(...)
が使えます。
サブクラスはすべてトランスフォームとして定義されていますが、ルックアップ名は Extract
サブクラスによってすでに予約されているため、フィールドは登録されていません。
使用例:
>>> 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
の切り捨て¶
- class TruncWeek(expression, output_field=None, tzinfo=None, **extra)[ソース]¶
その週の月曜日の午前0時に切り捨てます。
- kind = 'week'
これらは論理的には Trunc('date_field', kind)
と等価です。これらは kind
単位未満の日付のすべての部分を切り捨て、大ざっぱな日付のグループ化やフィルタリングに使用できます。 expression
には DateField
または DateTimeField
の output_field
を指定できます。
DateField
は時間要素を持たないので、日付部分を扱う Trunc
サブクラスだけが 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
の切り捨て¶
- class TruncDate(expression, tzinfo=None, **extra)[ソース]¶
- lookup_name = 'date'
- output_field = DateField()
TruncDate
は、組み込みの SQL の切り捨て関数を使わずに、 expression
を日付にキャストします。また、 DateTimeField
のトランスフォームとして __date
が登録されています。
- class TruncTime(expression, tzinfo=None, **extra)[ソース]¶
- lookup_name = 'time'
- output_field = TimeField()
TruncTime
は、組み込み SQL の切り捨て関数を使わずに、 expression
を時刻にキャストします。また、 DateTimeField
のトランスフォームとして __time
が登録されています。
これらは論理的には Trunc('datetime_field', kind)
と等価です。これらは kind
単位未満の日時のすべての部分を切り捨て、大ざっぱな datetime のグループ化やフィルタリングができます。 expression
は output_field
が DateTimeField
である必要があります。
使用例:
>>> 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
の切り捨て¶
- class TruncHour(expression, output_field=None, tzinfo=None, **extra)[ソース]
- kind = 'hour'
- class TruncMinute(expression, output_field=None, tzinfo=None, **extra)[ソース]
- kind = 'minute'
- class TruncSecond(expression, output_field=None, tzinfo=None, **extra)[ソース]
- kind = 'second'
これらは論理的には Trunc('time_field', kind)
と等価です。これらは kind
単位未満の時刻をすべて切り捨てるので、大ざっぱな時刻のグループ化やフィルタリングに使用できます。 expression
は output_field
に TimeField
または DateTimeField
を指定できます。
TimeField
は日付コンポーネントを持たないので、時間部分を扱う Trunc
サブクラスだけが 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
¶
数値フィールドまたは式の、絶対値を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、逆余弦(アークコサイン)を返します。式の値は -1 から 1 の範囲内でなければなりません。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、逆正弦(アークサイン)を返します。式の値は -1 から 1 の範囲でなければなりません。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の逆正接(アークタンジェント)を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
expression1 / expression2
の逆正接(アークタンジェント)を返します。
使用例:
>>> 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
¶
数値フィールドまたは式の値以上の最小の整数を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、余弦(コサイン)を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、余接(コタンジェント)を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式を、ラジアンから度へ変換します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
e
(自然対数の底) を数値フィールドまたは式の値でべき乗した値を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の値未満の最大の整数値を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、自然対数を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
2つの数値フィールドまたは式を受け取り、最初の値を底とする2番目の値の対数を返します。
使用例:
>>> 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
¶
2つの数値フィールドまたは式を受け取り、1つ目を2つ目で割った余りを返します(モジュロ演算)。
使用例:
>>> 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
Pi
¶
数学定数 π
の値を返します。
Power
¶
2つの数値フィールドまたは式を受け取り、1番目の値を2番目の値のべき乗にした値を返します。
使用例:
>>> 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
¶
数値フィールドまたは式を、度からラジアンに変換します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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)
Random
¶
0.0 ≤ x < 1.0
の範囲のランダムな値を返します。
Round
¶
数値フィールドまたは式を precision
(整数でなければなりません) 小数点以下の桁数に丸めます。デフォルトでは、最も近い整数に丸められます。半分の値を切り上げるか切り下げるかはデータベースによって異なります。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の符号 (-1, 0, 1) を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、正弦(サイン)を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
非負の数値フィールドまたは式の、平方根を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式の、正接(タンジェント)を返します。
使用例:
>>> 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
数値フィールドまたは式を受け取り、その式のテキスト表現を1文字として返します。Python の chr()
関数と同じように動作します。
Length
と同様に、 IntegerField
のトランスフォームとして登録できます。デフォルトのルックアップ名は chr
です。
使用例:
>>> 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
¶
少なくとも2つのテキストフィールドまたは式のリストを受け取り、連結したテキストを返します。各引数は text 型か char 型でなければなりません。もし TextField()
と CharField()
を連結したい場合は、必ず Django に output_field
が TextField()
であることを伝えてください。以下の例のように Value
を連結する場合にも output_field
を指定する必要があります。
この関数は決して null を返しません。null 引数があると式全体が null になるようなバックエンドでは、 Django は各 null 部分を最初に空文字列に変換にします。
使用例:
>>> # 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
¶
テキストフィールドまたは式の、最初から length
で指定した文字数までを返します。
使用例:
>>> 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
¶
単一のテキストフィールドまたは式を受け取り、その値が持つ文字数を返します。式が null の場合は、長さも null になります。
使用例:
>>> # 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)
トランスフォームとして登録することもできます。たとえば:
>>> 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
¶
単一のテキストフィールドまたは式を受け取り、小文字の表現を返します。
Length
と同様に、トランスフォームとして登録することもできます。
使用例:
>>> 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
¶
指定されたテキストフィールドまたは式の値の左側を fill_text
でパディングし、 length
文字の長さになるように値を返します。デフォルトの fill_text
はスペースです。
使用例:
>>> 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
LTrim
¶
Trim
と似ていますが、先頭の空白だけを取り除きます。
MD5
¶
単一のテキストフィールドまたは式を受け取り、その文字列の MD5 ハッシュを返します。
Length
と同様に、トランスフォームとして登録することもできます。
使用例:
>>> 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
¶
単一のテキストフィールドまたは式を受け取り、その式の最初の文字の Unicode コードポイント値を返します。Python の ord()
関数と似たような動作をしますが、式が1文字より長くても例外を発生させません。
Length
と同様に、トランスフォームとして登録することもできます。デフォルトのルックアップ名は ord
です。
使用例:
>>> 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
¶
テキストフィールドまたは式を number
回繰り返した値を返します。
使用例:
>>> 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
¶
expression
内で text
を replacement
で置き換えます。デフォルトの置換テキストは空文字列です。関数の引数は大文字小文字を区別します。
使用例:
>>> 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
¶
単一のテキストフィールドまたは式を受け取り、その式の文字を逆順に返します。
Length
と同様に、トランスフォームとして登録することもできます。デフォルトのルックアップ名は reverse
です。
使用例:
>>> 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
¶
テキストフィールドまたは式の最後から length
で指定した文字数分を返します。
使用例:
>>> 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
RPad
¶
LPad
と似ていますが、右側にパディングを行います。
RTrim
¶
Trim
と似ていますが、末尾の空白だけを削除します。
SHA1
, SHA224
, SHA256
, SHA384
, SHA512
¶
単一のテキストフィールドまたは式を受け取り、文字列の特定のハッシュを返します。
Length
と同様にトランスフォームとして登録することもできます。
使用例:
>>> 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 extension をインストールする必要があります。 CryptoExtension
マイグレーションオペレーションを使ってインストールできます。
Oracle
Oracle は SHA224
関数をサポートしていません。
StrIndex
¶
substring
が string
内で最初に出現する1から始まる位置に対応する正の整数を返します。もし substring
が見つからない場合は0を返します。
使用例:
>>> 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 では、データベーステーブルの 照合順序 (collation) によって、文字列(この関数の expression
や substring
など)の比較が大文字小文字を区別するかどうかが決まります。デフォルトでは大文字と小文字は区別されません。
Substr
¶
フィールドまたは式から、位置 pos
から始まる長さ length
の部分文字列を返します。位置は1から始まるインデックスであるため、位置は0より大きくなければなりません。もし length
が None
であれば、文字列の残りの部分が返されます。
使用例:
>>> # 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
¶
テキストフィールドまたは式の値を、先頭と末尾の空白を除去して返します。
使用例:
>>> 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
¶
単一のテキストフィールドまたは式を受け取り、大文字の表現を返します。
Length
と同様に、トランスフォームとして登録することもできます。
使用例:
>>> 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
を計算するために使用できる関数がいくつかあります。
CumeDist
¶
ウィンドウまたはパーティション内の値の累積分布を計算します。累積分布は、現在の行の前の行または前の行の数をフレーム内の行の総数で割ったものとして定義されます。
DenseRank
¶
Rank
と等価ですが、ギャップを持ちません。
FirstValue
¶
ウィンドウフレームの最初の行で評価された値を返します。そのような値が存在しない場合は None
を返します。
Lag
¶
offset
でオフセットされた値を計算し、そこに行が存在しない場合は default
を返します。
default
は expression
と同じ型でなければなりませんが、これはデータベースでだけ検証され、Python では検証されません。
MariaDB と default
MariaDB は default
パラメータを サポートしていません 。
LastValue
¶
FirstValue
と同様に、与えられたフレーム句の最後の値を計算します。
Lead
¶
与えられた フレーム の先頭の値を計算します。 offset
と default
は現在の行を基準として評価されます。
default
は expression
と同じ型でなければなりませんが、これはデータベースでだけ検証され、Python では検証されません。
MariaDB と default
MariaDB は default
パラメータを サポートしていません 。
NthValue
¶
ウィンドウ内のオフセット nth
(正の値である必要があります) からの相対行を計算します。行が存在しない場合は None
を返します。
データベースによっては、存在しない n 番目の値の扱いが異なる場合があります。例えば、 Oracle は文字ベースの式の場合、 None
ではなく空文字列を返します。Django はこのような場合、変換を行いません。
Ntile
¶
フレーム句の各行に対してパーティションを計算し、1から num_buckets
までの間で可能な限り均等に番号を割り振ります。行がいくつかのバケットに均等に分割されない場合、1つ以上のバケットがより頻繁に表されます。
PercentRank
¶
フレーム句の行の相対順位を計算します。この計算は評価と等価です:
(rank - 1) / (total rows - 1)
以下の表は、行の相対順位の計算について説明したものです:
行 No. |
値 |
順位 |
計算 |
相対順位 |
---|---|---|---|---|
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 |
Rank
¶
RowNumber
と同様に、この関数はウィンドウ内の行をランク付けします。計算された順位には隙間が生じることがあります。隙間のない順位を計算するには DenseRank
を使用します。
RowNumber
¶
ウィンドウフレーム のパーティショニングがない場合、フレーム句のソート、またはクエリ全体のソート順に従って行番号を計算します。