2012-12-22 47 views
1

看來,Django的開發人員都知道的事實,有沒有辦法在MySQL在這樣的計算字段篩選:Django的ORM:濾波計算領域的MySQL狀態/解決方法

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

OR

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

這是在https://code.djangoproject.com/ticket/8784中描述的,但不幸的是,它看起來將需要一年的時間來實現當前的速度。我理解開發團隊的理念,他們希望擺脫.extra(),因爲通過在該語句中編寫純SQL,代碼變得與數據庫無關。我認爲,處理計算領域是相當常見的任務在許多項目中,我目前面臨的,我解決不了的問題:我認爲大多數社區經常使用這骯髒的解決辦法:

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) 

的問題是:沒有任何人知道如何克服這種暫時的(希望)限制並完成任務?任何可能的選擇?

+0

是否爲您提供了一個解決方案來實現此字段(例如,保存方法)併爲物化數據寫入條件?這也會提高性能。 – danihp

+0

不幸的是,這不是一個選項 - 事實上,我在項目中所做的事情比上面真正天真的例子複雜得多,我無法將計算的字段保存到數據庫中,因爲它的值是使用某些輸入數據計算的,用戶,只在運行時間知道。雖然我承認您的解決方案適用於更簡單的場景。 – Ivan

+0

@Ivan:告訴我們你要做什麼樣的計算。它是模型領域的某種聚合還是隻是計算?取決於計算類型,可能有更簡單的解決方案。 –

回答

0

我找到了解決方案:我認爲在WHERE子句中再次計算該字段的速度會太慢,但是當我嘗試過它時,它變得相當快,而且不需要HAVING。下面是我的意思示範:

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

這基本上 - 如果你認爲你需要HAVING,嘗試測量時間與載有它與它在一次濾波運算計算字段比較時間在哪裏,然後得出結論。