django orm queryset - 如何执行 sql 查询 MIN/MAX FILTER
django orm queryset - how to perform sql query MIN/MAX FILTER
我正在尝试寻求帮助,为特定的 sql 语句创建 Django ORM 查询集(您也可以在此处 运行 它)
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=31c9431d6753e2fdd8df37bbc1869e88
特别是这个问题,我对包含以下内容的行更感兴趣:
MIN(created_at::time) FILTER (WHERE activity_type = 1) as min_time_in,
MAX(created_at::time) FILTER (WHERE activity_type = 2) as max_time_out
这里是整个 sql 如果可能转换为 django ORM 查询集
SELECT
created_at::date as created_date,
company_id,
employee_id,
MIN(created_at::time) FILTER (WHERE activity_type = 1) as min_time_in,
MAX(created_at::time) FILTER (WHERE activity_type = 2) as max_time_out
FROM
timerecord
where date(created_at) = '2020-11-18' and employee_id = 1
GROUP BY created_date, company_id, employee_id
ORDER BY created_date, employee_id
原查询:
SELECT
created_at::date as created_date,
company_id,
employee_id,
MIN(created_at::time) FILTER (WHERE activity_type = 1) as min_time_in,
MAX(created_at::time) FILTER (WHERE activity_type = 2) as max_time_out
FROM
timerecord
where date(created_at) = '2020-11-18' and employee_id = 1
GROUP BY created_date, company_id, employee_id
ORDER BY created_date, employee_id;
是conditional/selective aggregation的一个例子。上面的语法在 PostgreSQL/SQLite.
中可用
可以使用 CASE 表达式轻松重写为:
SELECT
created_at::date as created_date,
company_id,
employee_id,
MIN(CASE WHEN activity_type = 1 THEN created_at::time END)as min_time_in,
MAX(CASE WHEN activity_type = 2 THEN created_at::time END) as max_time_out
FROM
timerecord
where date(created_at) = '2020-11-18' and employee_id = 1
GROUP BY created_date, company_id, employee_id
ORDER BY created_date, employee_id;
任何现代 RDBMS 都支持它,Django 也支持它:
What if we want to find out how many clients there are for each account_type? We can nest conditional expression within aggregate functions to achieve this:
Client.objects.aggregate(
... regular=Count('pk', filter=Q(account_type=Client.REGULAR)),
... gold=Count('pk', filter=Q(account_type=Client.GOLD)),
... platinum=Count('pk', filter=Q(account_type=Client.PLATINUM)),
... )
This aggregate produces a query with the SQL 2003 FILTER WHERE syntax on databases that support it
...
On other databases, this is emulated using a CASE statement
您可以将 aggregate()
--(doc) method or (annotate()
--(doc) method) to get the result. For that, you must use the Min()
and Max()
数据库函数与 filter
参数一起使用。
from django.db.models import Min, Q, Max
agg_response = TimeRecord.objects.aggregate(
<b>min_time_in=Min("created_at", filter=Q(activity_type=1)),
max_time_out=Max("created_at", filter=Q(activity_type=2)),</b>
)
我正在尝试寻求帮助,为特定的 sql 语句创建 Django ORM 查询集(您也可以在此处 运行 它) https://dbfiddle.uk/?rdbms=postgres_13&fiddle=31c9431d6753e2fdd8df37bbc1869e88
特别是这个问题,我对包含以下内容的行更感兴趣:
MIN(created_at::time) FILTER (WHERE activity_type = 1) as min_time_in,
MAX(created_at::time) FILTER (WHERE activity_type = 2) as max_time_out
这里是整个 sql 如果可能转换为 django ORM 查询集
SELECT
created_at::date as created_date,
company_id,
employee_id,
MIN(created_at::time) FILTER (WHERE activity_type = 1) as min_time_in,
MAX(created_at::time) FILTER (WHERE activity_type = 2) as max_time_out
FROM
timerecord
where date(created_at) = '2020-11-18' and employee_id = 1
GROUP BY created_date, company_id, employee_id
ORDER BY created_date, employee_id
原查询:
SELECT
created_at::date as created_date,
company_id,
employee_id,
MIN(created_at::time) FILTER (WHERE activity_type = 1) as min_time_in,
MAX(created_at::time) FILTER (WHERE activity_type = 2) as max_time_out
FROM
timerecord
where date(created_at) = '2020-11-18' and employee_id = 1
GROUP BY created_date, company_id, employee_id
ORDER BY created_date, employee_id;
是conditional/selective aggregation的一个例子。上面的语法在 PostgreSQL/SQLite.
中可用可以使用 CASE 表达式轻松重写为:
SELECT
created_at::date as created_date,
company_id,
employee_id,
MIN(CASE WHEN activity_type = 1 THEN created_at::time END)as min_time_in,
MAX(CASE WHEN activity_type = 2 THEN created_at::time END) as max_time_out
FROM
timerecord
where date(created_at) = '2020-11-18' and employee_id = 1
GROUP BY created_date, company_id, employee_id
ORDER BY created_date, employee_id;
任何现代 RDBMS 都支持它,Django 也支持它:
What if we want to find out how many clients there are for each account_type? We can nest conditional expression within aggregate functions to achieve this:
Client.objects.aggregate( ... regular=Count('pk', filter=Q(account_type=Client.REGULAR)), ... gold=Count('pk', filter=Q(account_type=Client.GOLD)), ... platinum=Count('pk', filter=Q(account_type=Client.PLATINUM)), ... )
This aggregate produces a query with the SQL 2003 FILTER WHERE syntax on databases that support it
...
On other databases, this is emulated using a CASE statement
您可以将 aggregate()
--(doc) method or (annotate()
--(doc) method) to get the result. For that, you must use the Min()
and Max()
数据库函数与 filter
参数一起使用。
from django.db.models import Min, Q, Max
agg_response = TimeRecord.objects.aggregate(
<b>min_time_in=Min("created_at", filter=Q(activity_type=1)),
max_time_out=Max("created_at", filter=Q(activity_type=2)),</b>
)