【问题标题】:Django equivalent of SELECT * GROUP BY in MySQLDjango 相当于 MySQL 中的 SELECT * GROUP BY
【发布时间】: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


【解决方案1】:

首先导入 Max 函数如下所示:

from django.db.models import Max

然后,这就是你需要的:

MyModel.objects.filter(id__lte=50).values('group_id').order_by('group_id').annotate(date_time_max=Max('date_time'))

【讨论】:

  • 我想我以某种方式设法编写了该查询,但它没有满足我的需要。我需要获取完整的对象实例,这仅返回 group_id 以及 date_time_max
猜你喜欢
  • 2010-10-24
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
相关资源
最近更新 更多