如何计算具有多个分组依据的 Django 查询集的单个字段?

How to count a single field of a django queryset with multiple group by?

假设我有一个查询集qs。我按查询集分组如下:

(
    qs.annotate(
        catering_price_enabled=F("outlet__library__settings__sligro_catering_price_enabled"),
    )
    .values("assortment_sync_id", "catering_price_enabled")
    .order_by("assortment_sync_id", "catering_price_enabled")
    .distinct("assortment_sync_id", "catering_price_enabled")
)

我得到类似的东西:

<QuerySet [
   {'assortment_sync_id': '01234', 'catering_price_enabled': False}, 
   {'assortment_sync_id': '01234', 'catering_price_enabled': None}, 
   {'assortment_sync_id': '56789', 'catering_price_enabled': None},
]>

我想做的是 annotate 这个查询集,这样我最终可以过滤值 > 1。换句话说,每个 assortment_sync_id 只能有 catering_price_enabled.

的值

如果我添加 .annotate(count=Count("assortment_sync_id")) django raises NotImplementedError: annotate() + distinct(fields) is not implemented. 我尝试了这种方法,因为它显然只适用于一个字段。

如何获得下面的预期输出?

<QuerySet [
   {'assortment_sync_id': '01234', 'catering_price_enabled': False, 'count': 2}, 
   {'assortment_sync_id': '01234', 'catering_price_enabled': None, 'count': 2}, 
   {'assortment_sync_id': '56789', 'catering_price_enabled': None, 'count': 1},
]>

“我想做的是注释这个查询集,这样我最终可以过滤值 > 1。”

如果你想得到 assortment_sync_id 大于一个的对象:

qs.annotate(
catering_price_enabled=F("outlet__library__settings__sligro_catering_price_enabled"),)
.values("assortment_sync_id", "catering_price_enabled")
.order_by("assortment_sync_id", "catering_price_enabled")
.distinct("assortment_sync_id", "catering_price_enabled")

qs.filter(assortment_sync_id__gte=1)
  1. 使用 .distinct() 查找具有 assortment_sync_idcatering_price_enabled
  2. 的不同行
  3. 创建一个子查询,从 1. 过滤 distinct_queryset 中的 pk,按 assortment_sync_id 分组并计数 assortment_sync_id
  4. 通过在来自 1. 的不同查询集中过滤 pk 创建结果查询集,然后使用来自 2. 的计数查询集在最终结果中进行注释。
qs = qs.annotate(catering_price_enabled=F("outlet__library__settings__sligro_catering_price_enabled"))

distinct_qs = qs.distinct("assortment_sync_id", "catering_price_enabled")

count_qs = (
    qs.filter(
        pk__in=distinct_qs.values("pk"),
        assortment_sync_id=models.OuterRef("assortment_sync_id")
    )
    .values("assortment_sync_id")
    .order_by("assortment_sync_id")
    .annotate(count=models.Count("*"))
    .values("count")
)

result = (
    qs.filter(pk__in=distinct_qs.values("pk"))
    .annotate(
        count=models.Subquery(count_qs)
    ).values("assortment_sync_id", "catering_price_enabled", "count")
)