【发布时间】:2014-09-27 00:05:52
【问题描述】:
我正在使用 Django ORM 执行一个看起来像这样的复杂查询:
user_ids = MyLog.objects.values('user_id').annotate(
last_configured=Max('configured')
).exclude(
last_configured__lt=earlier_date
).filter(content_type_id=configuration_content_type).values_list('user_id', flat=True)
计算结果为:
SELECT `customer_mylog`.`user_id`, MAX(`customer_mylog`.`configured`)
AS `last_configured` FROM `customer_mylog`
WHERE (`customer_mylog`.`content_type_id` = 654 )
GROUP BY `customer_mylog`.`user_id`
HAVING NOT (MAX(`customer_mylog`.`configured`) < 2014-04-19 20:22:38.729416 )
ORDER BY NULL
此时,我确信查询尚未执行,除非我执行类似len(user_ids) 之类的操作,而我没有这样做。然后我通过执行以下操作对其进行修改:
new_user_ids = User.objects.filter(pk__in=user_ids).exclude(date_joined__lt=earlier_date).exists()
将原始查询更改为:
SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`la
st_name`, `auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`, `auth_user`.`
is_active`, `auth_user`.`is_superuser`, `auth_user`.`last_login`, `auth_user`.`date_joined`
FROM `auth_user` WHERE (`auth_user`.`id` IN (SELECT U0.`user_id` FROM `customer_mylo
g` U0 WHERE (U0.`content_type_id` = 654 ) GROUP BY U0.`user_id` HAVING NOT (MAX(U0.`configured`)
< 2014-05-04 13:04:48.204187 ) ORDER BY NULL) AND NOT (`auth_user`.`date_joined` < 2014-05-0
4 13:04:48 ))
如果我通过执行 list(new_user_ids) 之类的操作来执行查询,它永远不会完成执行。它既不会失败,也不会给出任何错误消息。
因此,我尝试了以下方法,它以某种方式完美地工作。
for user_id in user_ids:
if User.objects.filter(pk=user_id).exclude(date_joined__lt=earlier_date).exists():
new_user_ids.append(user_id)
为什么前一种方法不起作用,尽管两者在尝试做的事情上基本相似?
【问题讨论】:
-
除非您要求它,否则它永远不会评估:docs.djangoproject.com/en/1.6/ref/models/querysets/…
-
@petkostas 我想我无法在问题中正确解释自己。请再次查看。
-
如果你尝试通过len来评估它?你得到了什么?如 django 文档中所述(关于列表):
Be warned, though, that this could have a large memory overhead, because Django will load each element of the list into memory. -
另外尝试在 shell 中运行查询集并检查会发生什么。
-
您使用哪个数据库和数据库版本?旧的 MySQL 版本确实没有针对复杂的子查询进行很好的优化。
标签: python mysql django orm django-queryset