我有3张桌子:
卡车,其中包含以下字段:id
,name
....
菜单,其中包含以下字段:id
,itemname
,id_foodtype
,id_truck
...
食物类型,字段为:id
,type
...
我希望得到如下摘要:
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
代码,我的任何查询都会返回我预期的确切结果。
如何使用Left Join
返回foodtypes
的结果,包括menu
中包含零元素的Employee1
?
答案 0 :(得分:1)
LEFT JOIN的方向取决于您启动查询的对象。如果它从Menu
开始,您将永远不会看到所选菜单项未使用FoodType
。然后重要的是过滤(在你的情况下通过卡车)这样的方式,也允许空值Menu.id,以便可以获得Count == 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对象。
<强>脚注强>:
如果您已定义related_name,则名称menu_set
应替换为外键related_name
的真实id_foodtype
。
class Menu(models.Model):
id_foodtype = models.ForeignKey('FoodType', on_delete=models.DO_NOTHING,
db_column='id_foodtype', related_name='menu_set'))
...
如果你开始一个新项目,我建议将外键重命名为不带“id”的名称,db_column字段带有“id”。然后menu_item.foodtype
是食物对象,menu_item.id_foodtype
是id
。