我想执行一个简单的查询,如:
select *,count('id') from menu_permission group by menu_id
在django格式中,我尝试过:
MenuPermission.objects.all().values('menu_id').annotate(Count('id))
只选择menu_id。查询执行:
SELECT `menu_permission`.`menu_id`, COUNT(`menu_permission`.`id`) AS `id__count` FROM `menu_permission` GROUP BY `menu_permission`.`menu_id`
但我也需要其他领域。如果我尝试:
MenuPermission.objects.all().values('id','menu_id').annotate(Count('id))
它按条件添加'id'。
GROUP BY `menu_permission`.`id`
结果我没有得到预期的结果。我怎样才能按组只按1列获取所有对象?
答案 0 :(得分:1)
您正在尝试实现此SQL:
select *, count('id') from menu_permission group by menu_id
但是,通常情况下,SQL要求使用group by子句时,您只能在要进行分组的选择中包括那些列名。这不是django问题,而是SQL group by的工作方式。
这些行按这些列分组,因此如果您希望将这些列合并为一个值,则可以将这些列包括在select中。您不能直接包含其他列,因为它们可能具有多个值(因为行已分组)。
例如,如果您有一列名为“ permission_code”的列,则在按menu_id对行进行分组时,可以在“ permission_code”列中要求一个值的数组。
取决于您使用的SQL风格,在PostgreSQL中可能是这样的:
select menu_id, array_agg(permission_code), count(id) from menu_permissions group by menu_id
为此可以构建sijanary django查询集。
希望这会有所帮助,但是如果需要,请分享更多有关您需要执行的操作以及数据模型的信息。
答案 1 :(得分:0)
query = MenuPermission.objects.values('menu_id').annotate(menu_id_count=Count('menu_id'))
您可以按print(query.query)
答案 2 :(得分:0)
您可以使用以下代码:
MenuPermission.objects.values('menu_id').annotate(Count('id)).values('field1', 'field2', 'field3'...)
答案 3 :(得分:0)
您可以尝试子查询来执行所需的操作。
就我而言,我有两个表:TCEFORM.tx_news_domain_model_news.categories.PAGE_TSCONFIG_IDLIST = 89,99
和Item
,其中Transaction
链接到item_id
首先,我准备按Item
组的Transaction
子查询,在这里我将所有item_id
字段加起来,并将amount
标记为外部查询的pk。
item_id
然后,我从per_item_total=Transaction.objects.values('item_id').annotate(total=Sum('amount')).filter(item_id=OuterRef('pk'))
中选择所有行,并在item
域中选择子查询结果。
total
这将产生以下SQL:
items_with_total=Item.objects.annotate(total=Subquery(per_item_total.values('total')))
答案 4 :(得分:0)
当前按预期运行的唯一方法是基于希望GROUP BY所基于的模型来进行查询。 在您的情况下,您似乎具有菜单模型(menu_id字段外键),因此这样做可以为您提供所需的信息,并允许从MenuPermission模型中获取其他汇总信息,但仅按Menu.id字段分组:>
Menu.objects.annotate(perm_count=Count('menupermission__id').values(perm_count)
当然,如果您只需要单个计数,就不需要“注释”中间步骤。
答案 5 :(得分:-1)
此解决方案不起作用,所有字段都以group by子句结尾,将其保留在此处,因为它可能仍然对某人有用。
model_fields = queryset.model._meta.get_fields()
queryset = queryset.values('menu_id') \
.annotate(
count=Count('id'),
**{field.name: F(field.name) for field in model_fields}
)
我正在做的是获取list of fields of our model,并建立一个以字段名称为键的字典和一个F instance,以字段名称为参数。
当unpacked (the **)时,它被解释为传递给注释函数的命名参数。
例如,如果我们在模型上有一个“名称”字段,则此带注释的调用最终将等于此:
queryset = queryset.values('menu_id') \
.annotate(
count=Count('id'),
name=F("name")
)