sql - SQL 代码转换成单个 Django ORM 查询?
问题描述
我正在尝试将以下 SQL 查询转换为单个 Django 查询,以最大限度地减少执行的 sql 查询的数量,但是除了使用 for 循环之外我无法做到这一点。
如果有人能给我提供预期的 Django 查询,我将不胜感激
SQL查询:
select FUND_ID, REPORT_DATE, PURCHASE_NAV_PER_SHARE
FROM FUNDS_HISTORY
WHERE REPORT_DATE = (
SELECT Max(REPORT_DATE)
FROM FUNDS_HISTORY fund_history
where fund_history.FUND_ID = FUNDS_HISTORY.FUND_ID
)
楷模:
class Fund(models.Model):
name_en = models.CharField(max_length=256, blank=True, null=True)
class History(models.Model):
fund = models.ForeignKey('funds.Fund', on_delete=models.CASCADE, blank=True, null=True)
purchase_nav_per_share = models.BigIntegerField(blank=True, null=True)
report_date = models.DateField(blank=True, null=True)
解决方案
我们可以History
用相关的最大值来注释对象Fund
,例如:
History.objects.annotate(
max_date=Max('fund__history__report_date')
).filter(
report_date=F('max_date')
)
或者更简单一点:
History.objects.filter(
report_date=Max('fund__history__report_date')
)
您可以通过以下方式稍微提高性能:
from django.db.models import Max, OuterRef, Subquery
History.objects.filter(
report_date=Subquery(
History.objects.filter(
fund_id=OuterRef('fund_id')
).values('fund_id').annotate(
last_date=Max('report_date')
).values('last_date')[:1]
)
)
这将产生一个如下所示的查询:
SELECT history.id, history.fund_id, history.purchase_nav_per_share, history.report_date
FROM history
WHERE history.report_date = (
SELECT MAX(U0.report_date) AS last_date
FROM history U0
WHERE U0.fund_id = history.fund_id
GROUP BY U0.fund_id
LIMIT 1
)
以上与问题中的查询非常相似。
我们在这里获取History
对象,这通常比掌握值本身要好,因为这是一种“原始痴迷”反模式。
推荐阅读
- c# - 使用 ASP.NET MVC 将图像上传到本地数据库
- java - clean & build 和 build 之间的区别?
- r - 为 R 中的曲线积分返回 0
- javascript - 使用 php 进行 Ajax 调用
- ibm-mobilefirst - 证书固定在本机 android Mobilefirst 8.0 应用程序中不起作用
- android - Listview OnItemClickListener 在 MainActivity 上工作,但不在类似的 TaskActivity 上
- android - Firestore 无法获取文档,因为客户端处于脱机状态
- ajax - codeignitter 中的 ajax 表单 - 发送生成的表单
- mysql - 添加连接后 MySQL 查询中断
- tableau-api - 在日期之间计数的计算字段