Django-如果另外一列不同,则求和

问题描述 投票:0回答:2

我在djagno中有两个表

class Item(models.model):
    name = models.TextField()
    type = models.ForeignKey(ItemType)
    quantity = models.IntegerField()

class ProductionRecord(models.model):
    item = models.ForeignKey(Item)
    done = models.IntegerField()

我想做的是将物品按类型分组,将所需物品的总数相加,然后对所生产物品的总数相加。

我相当接近,但我遇到的问题是,在执行.annotate(Sum("quantity"))时,如果一个项目具有多个生产记录,它将根据每个记录再次对数量求和。

下面是连接表之后和分组之前我当前数据集的一个示例。

+--------+--------+--------------+----------------------+ | ItemId | TypeId | ItemQuantity | ProductionRecordDone | +--------+--------+--------------+----------------------+ | 1257 | 7 | 4 | 1 | | 1257 | 7 | 4 | 4 | | 1259 | 7 | 4 | 4 | | 1261 | 7 | 4 | 0 | | 1263 | 7 | 4 | 4 | | 1265 | 7 | 4 | 0 | +--------+--------+--------------+----------------------+

在数量列上进行正常求和时,由于对项目id = 1257进行两次求和,因此返回24。

但是分组后我想返回的是:

+--------+--------------+------+ | TypeId | ItemQuantity | Done | +--------+--------------+------+ | 7 | 20 | 13 | +--------+--------------+------+

这是我当前的python代码供参考

Item.objects.values("type__name", "type__id") \
            .annotate(total_done=Coalesce(Sum("productionrecord__done"), 0),
                      total_quantity=Coalesce(Sum("quantity",), 1))

是否有任何代码可用于仅对ItemId不同的行中的数量求和?

sql django django-orm
2个回答
0
投票

尝试:

queryset = Item.objects.values("type__name", "type__id") \
    .filter(productionrecord__done=True) \
    .annotate(total_done=Count("*"),
              total_quantity=Sum("quantity"))

请不要显示queryset.query,否则无法正常工作。


0
投票

这无法在一个查询中完成,因为当与生产记录进行外部联接时,数量的总和将会复合。但是,您可以执行两个查询,然后合并字典:

    data = {}
    quantities = (
        Item.objects.order_by("type_id")
        .values("type_id")
        .annotate(to_produce=Coalesce(Sum("quantity"), 1),)
    )
    for item in quantities:
        type_id = item.pop("type_id")
        data[type_id] = item
    done = (
        Item.objects.order_by("type_id")
        .values("type_id")
        .annotate(done=Coalesce(Sum("productionrecord__done"), 1),)
    )
    for item in done:
        item_type_id = item.pop("type_id")
        data[type_id].update(item)

    for type_id, numbers in data.items():
        print(type_id, numbers.get("to_produce"), numbers.get("done"))
© www.soinside.com 2019 - 2024. All rights reserved.