1

似乎 Django 开发人员意识到在 MySQL 中无法过滤这样的计算字段:

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['total < 10'])

或者

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }).filter(total__lt=10)

这在https://code.djangoproject.com/ticket/8784中有所描述,但不幸的是,以目前的速度实施似乎还需要一年的时间。我理解开发团队的担忧,即理想情况下他们希望摆脱 .extra() ,因为通过在该语句中编写纯 SQL 代码变得与 DB 无关。我相信在许多项目中处理计算字段是相当普遍的任务,我目前面临着我无法解决的问题:我认为大多数社区经常使用这种肮脏的解决方法:

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['1 HAVING total < 10'])

实际上它有效,但只有在您需要对上述语句的结果添加过滤器的那一刻:

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['1 HAVING total < 10']).filter(id__gt=300)

这不再起作用,因为它转换为错误的 SQL 语句:

SELECT id, ..., (SOME CALCULATION) AS total
FROM some_table
WHERE (1 AND HAVING total < 10 AND id > 300)

我想要实现的是在自定义模型管理器中有某种​​限制,这将允许我编写如下代码:

class SomeModelManager(models.Manager):
  def apply_total_restriction(self, restriction_num):
    return self.extra(select={ 'total': 'CALCULATION GOES HERE' }).filter(total__lt=restriction_num)

...

SomeModel.objects.apply_total_restriction(restriction_num).filter(created_by_id__exact=1)

问题是:有人知道如何克服这个暂时的(希望如此)限制并完成任务吗?任何可能的替代方案?

4

1 回答 1

0

我找到了解决方案:我认为在 WHERE 子句中再次计算该字段会太慢,但是当我尝试它时它变得非常快并且不需要 HAVING。下面是我的意思的演示:

SELECT (a + b / 2) as 'c', a, b FROM table WHERE (a + b / 2) >= 20 AND a != b

基本上就是这样 - 如果您认为需要 HAVING,请尝试使用 HAVING 测量时间,并将其与再次计算计算字段的时间进行比较,然后在 WHERE 中对其进行过滤,然后得出结论。

于 2013-01-07T19:19:14.413 回答