如何在不使用聚合函数的情况下在Django中执行GROUP BY?

时间:2011-08-15 21:41:01

标签: django django-models

如何在不调用Max,Sum,Avg等聚合函数的情况下在Django中执行GROUP BY?

在我的情况下,我有一个包含{ local_path, parent, grandparent }列的表格,我想要SELECT local_path FROM ... WHERE grandparent = "foo" GROUP BY parent。将有多个行具有祖父母“foo”和相同的父级,但我只想要一个(任何一个)他们的local_path。

正如您所看到的,我不想取任何值的总值。而且我无法使distinct()工作,因为我想找到非独特的local_paths。

我搜索并阅读了没有任何运气的文档。谢谢!

3 个答案:

答案 0 :(得分:2)

您可以使用order_by('parent')然后在模板中使用{%ifchanged%}来仅显示其中一个。 https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#ifchanged

答案 1 :(得分:1)

这是一个使Django在不运行聚合函数的情况下执行GROUP BY查询的技巧。我们创建了一个自定义Func子类,该子类被Django视为聚合函数,但实际上在SQL查询中仅求值为NULL

from django.db.models import Func, CharField


class NullAgg(Func):
    """Annotation that causes GROUP BY without aggregating.

    A fake aggregate Func class that can be used in an annotation to cause
    a query to perform a GROUP BY without also performing an aggregate
    operation that would require the server to enumerate all rows in every
    group.

    Takes no constructor arguments and produces a value of NULL.

    Example:
        ContentType.objects.values('app_label').annotate(na=NullAgg())
    """
    template = 'NULL'
    contains_aggregate = True
    window_compatible = False
    arity = 0
    output_field = CharField()

答案 2 :(得分:0)

如果GROUP BY parent使用WHERE grandparent =然后SELECT local_path,那么SQL查询是否有效?它不应该抱怨你只允许SELECT“分组”条款的聚合吗?

我想找到非独特的local_paths

你没有说,所以我假设local_path是一个字符串,parentgrandparentForeignKey ModelPerson

from collections import defaultdict
paths = defaultdict(list)  # parent_id -> list of paths to grandpa 'foo'

for parent_id in User.objects.filter(grandparent='foo').only('parent__id'):
    for path in User.objects.filter(grandparent='foo', parent__id=parent_id) \
        .only('local_path'):
        paths[parent__id] = path.local_path

paths将是local_path

为不同“父母”保留grandparent='foo'值的词典