2017-10-19 95 views
1

我有3個表:Django的查詢ForeignKey的COUNT()零

卡車與字段:idname ....

菜單與字段:iditemnameid_foodtypeid_truck ...

Foodtype與領域:idtype ...

我想得到這樣的總結:

id name    total 
10 Alcoholic drink 0 
5 Appetizer   11 

我的問題是返回結果與0元素

我試過SQL查詢是這樣的:

SELECT 
    ft.id, ft.name, COUNT(me.id) total 
FROM 
    foodtype ft LEFT JOIN menu me 
     ON ft.id = me.id_foodtype 
    LEFT JOIN truck tr 
     ON tr.id = me.id_truck AND tr.id = 3 
GROUP BY ft.id, ft.name 
ORDER BY ft.name 

查詢在Django

Menu.objects.filter(id_truck=3).values("id_foodtype").annotate(cnt=Count("id_foodtype")) 

但是,無論是與Zero元素顯示結果。

在將此查詢轉換爲Python代碼的時刻,我的任何查詢都會返回我期望的確切結果。 如何在menu中返回Left Join的結果,包括foodtypes和零個元素?

+0

這是更多的問題sql-postgres比django –

+0

我編輯你的問題可以更容易搜索,希望它是可以接受的。我也編輯了一些我的答案。 – hynekcer

回答

0

LEFT JOIN的方向取決於開始查詢的對象。如果從Menu開始,您將永遠不會看到FoodType未被選定的菜單項使用。然後是很重要的(在你的情況下,通過卡車)來過濾也空值Menu.id允許爲了能得到計數== 0,

from django.db.models import Q 
qs = (
    FoodType.objects 
    .filter(Q(menu_set__id_truck=3) | Q(menu_set__id__isnull=True)) 
    .values() # not necessary, but useful if you want a dict, not a Model object 
    .annotate(cnt=models.Count("menu_set__id")) 
) 

驗證這樣的方式:

>>> print(str(qs.query)) 
SELECT foodtype.id, foodtype..., COUNT(menu.id) AS cnt 
FROM foodtype 
LEFT OUTER JOIN menu ON (foodtype.id = menu.id_foodtype) 
WHERE _menu.id_truck = 3 OR menu.id IS NULL) 
GROUP BY foodtype.id 

它適用於當前最新和最舊的Django 2.0b1和1.8。

查詢結果是否與.values()一致。結果是具有cnt屬性的字典或FoodType對象。


腳註
名稱menu_set應的外鍵id_foodtype真正related_name被替換,如果你已經定義了related_name。

class Menu(models.Model): 
    id_foodtype = models.ForeignKey('FoodType', on_delete=models.DO_NOTHING, 
            db_column='id_foodtype', related_name='menu_set')) 
    ... 

如果你開始一個新的項目,我建議重新命名的外鍵的名稱沒有「身份證」和db_column場是「身份證」。然後menu_item.foodtype是一個食物對象和menu_item.id_foodtypeid