关于 annotate 运行与预想不符(group by 多一个字段)的问题

解决

由于在 model 中的 meta 添加了默认的 order_by,导致使用 annotate 时一直无法满足预期的结果,只需要添加空的 order_by 重置排序,或者删去默认排序即可。

过程

在 django 中,使用 anotate 来做分组查询。以下是对 annotate 的介绍以及为什么我会出现问题的描述。

假设我们有这么一张表 table1:

id用户名 username系统 system
1张三Windows
2李四Android
3王五IOS
4赵六Windows

如果我们要对统计有多少人在使用使用这些系统,只需要这么一小句 SQL 语句

select system, count(device) from table1 group by system;

输出如下:

+---------+---------------+
| device  | count(device) |
+---------+---------------+
| Android |             1 |
| IOS     |             1 |
| Windows |             2 |
+---------+---------------+

而在 django 中理论上只需要这样即可完成上述操作(假设 Table1 为模型类):

from django.db.models import Count

queryset = Table1.objects.values("device").annotate(Count("device"))

然而事实并不如我所愿,在语句执行之后,发现目标字段并没有进行分组,而是单独分开成了一个组,结果大概就像下面这样,所以 Count(“device”) 就变成了 1。

+---------+---------------+
| device  | count(device) |
+---------+---------------+
| Android |             1 |
| IOS     |             1 |
| Windows |             1 |
| Windows |             1 |
+---------+---------------+

将 queryset 的原始对象打印,发现该语句多了一个用于 group by 的字段,大概如下:

>>> print(queryset.query)
SELECT `table1`.`device`, COUNT(`table1`.`device`) FROM `table1` GROUP BY `table1`.`device`, `table1`.`create_time`

可以看到是 group by 之后多了 create_time 字段,这个字段是我在创建模型类的时候填写的默认排序,即 class meta 中的 ordering。在翻阅了不少东西过后,发现解决它就得从排序下手,要么删除默认排序,要么使用一个空的排序来重置它。于是上面的 django 代码可以改写成这样。

queryset = Table1.objects.values("device").annotate(Count("device")).order_by()

于是就这么正常了,至于空的 order_by,相当于 ORDER BY NULL。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值