Django获取所有值Group By特定的一个字段

时间:2016-08-09 10:40:24

标签: django django-models

我想执行一个简单的查询,如:

    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列获取所有对象?

6 个答案:

答案 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)

检查SQL查询

答案 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")
            )