【发布时间】:2020-05-11 12:15:03
【问题描述】:
我在 Django ORM 中使用 .annotate() 和 .aggregate() 时遇到问题。
我的表结构:
-----------------------------------------------------
| id group_id date_time |
| ================================================= |
| 1 1 2020-01-25 19:51:46.603859 |
| 2 2 2020-01-24 18:40:24.301419 |
| 3 1 2020-01-25 20:14:11.123860 |
| 4 2 2020-01-25 05:20:21.507901 |
-----------------------------------------------------
//已编辑
我有以下 MySQL 查询:
SELECT m.*
FROM my_table m
JOIN (
SELECT group_id, max(date_time) as max_date
FROM my_table
GROUP BY group_id
) as s on m.group_id=s.group_id and m.date_time=s.max_date
返回:
-----------------------------------------------------
| id group_id date_time |
| ================================================= |
| 3 1 2020-01-25 19:51:46.603859 |
| 4 2 2020-01-24 18:40:24.301419 |
-----------------------------------------------------
我正在尝试将其转换为 Django ORM,这样我就可以拥有完整的 QuerySet 对象。直到现在我一直在使用这个代码:
unique_qs = MyModel.objects.filter(id__lte=50).values_list('group_id', flat=True).distinct()
unique_obj = []
for qs in unique_qs:
unique_obj.append(MyModel.objects.filter(group_id = qs).latest('date_time'))
但这确实效率低下且耗时。你能给我一些关于如何实现它的指导吗?
【问题讨论】:
-
您的原始查询不正确。它与较新的 MySQL 版本不兼容,因为您使用的列列表不包含您的选择 (id) 中的所有非聚合列。不知道你在查询之后会遇到什么。如果您的意图只是获得每个组的最大次数,请不要使用 *,而是使用
select group_id, max(date_time)。该查询在旧 MySQL 版本和关闭sql_mode=only_full_group_by的较新版本中运行。修复查询后,执行 Django ORM 会更容易。 -
@slaakso 你用的是什么版本?我正在使用 10.4.11-MariaDB,它工作得很好。通过文字我想要实现的目标:我需要为每个 group_id 选择一个具有最大 date_time 的完整行
-
MariaDB 默认没有开启
ONLY_FULL_GROUP_BY模式(尽管恕我直言应该有)。 MySQL 已经在 5.7.5 中将其添加为默认值。 MySQL/MariaDB 中最常见的错误来源可能是GROUP BY的错误使用。ONLY_FULL_GROUP_BY可以解决这个问题,因为用户将收到他们可能遇到的错误的通知。您试图通过查询实现什么?请注意,尽管 MariaDB 与 max(date_time) 无关,但它返回 ID 1,默认情况下它只是随机选择一个。见db-fiddle.com/f/hGiaVxWKbAc7QHX8NMN5Dy/0 -
知道了,确实我没有启用
ONLY_FULL_GROUP_BY选项。现在它确实给出了错误。那么我有什么办法来解决这个问题呢?基本上我需要的是为每个组选择最新记录。
标签: python mysql django django-models