django 使用子查询来注释外键字段的不同值的计数
django use subquery to annotate count of distinct values of foreign key field
我正在尝试注释不同产品的数量,但到目前为止我还没有成功。我收到如下错误:
ProgrammingError: subquery must return only one column
LINE 1: ..._id", "shop_selectedproduct"."create_date", COUNT((SELECT U0...
我有以下型号:
class ShopItem(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
store = models.ForeignKey(to=Store, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
class SelectedProduct(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="products", null=True, blank=True)
product = models.ForeignKey(ShopItem, null=True, blank=True, on_delete=models.SET_NULL)
class Order(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
store = models.ForeignKey(Store, on_delete=models.CASCADE, related_name="orders")
status = models.PositiveIntegerField(choices=OrderStatus.choices, default=OrderStatus.CART)
number = models.CharField(max_length=36, blank=True, null=True)
我尝试计算不同的商品,例如 p1, p2, p3, p4 and p5
其中 p1 数量应该是 3,因为它被选择了三次,而其他人可能只有一个数量,因为我们只选择了每个产品中的一个。
我的原始实现:
products = order.products.all().annotate(quantity=Count("product"))
但是对于所有产品,这总是 returns 1,尽管它们被选择了多次。
我现在尝试解决这个问题是:
# order = 1
SelectedProduct.objects.filter(order=order).annotate(quantity=Count(Subquery(ShopItem.objects.filter(id=OuterRef("product")))))
无论如何我可以计算产品被选中的次数并在 selected_product 上注释,例如:
p1.quanity
> 3
p2.quanity
> 1
p3.quanity
> 1
p4.quanity
> 1
p5.quanity
> 1
如有任何见解,我将不胜感激。
编辑:我进一步的尝试:
subquery = Subquery(ShopItem.objects.filter(selectedproduct__order=order, selectedproduct=OuterRef('id')).order_by()
.values('selectedproduct').annotate(count=Count('pk'))
.values('count'), output_field=IntegerField())
SelectedProduct.objects.filter(order=order).annotate(child_count=Coalesce(Subquery, 0))
它抛出 RecursionError: maximum recursion depth exceeded
假设您在 per-order 基础上执行此操作,您可以从订单实例本身查询并在相关管理器上注释?
# Assuming the instance is self
self.products.all().annotate(
quantity=Count(
'product', distinct=True
),
)
试试这个:
SelectedProduct.objects.filter(
order=order
).values(
'product'
).annotate(
quantity=Count('product')
).order_by('product')
此外,您可以统计所有已选择产品的数据:
SelectedProduct.objects.values(
'product'
).annotate(
quantity=Count('product')
).order_by('product')
如果您想计算所有产品的所有选定项目
ShopItem.objects.annotate(
quantity=Count('selectedproduct')
)
更新 1
至returns相关对象字段
from django.db.models import F
SelectedProduct.objects.values(
'product'
).annotate(
quantity=Count('product'),
item_name = F('product__name'),
item_store = F('product__store'),
# also, you can use
#item_store_name= F('product__store__name'),
).order_by('product')
给定一个 order
实例,如果您想要该订单中的 ShopItem
的集合,并在订单中注释了它们的数量,您可以查询 ShopItem
table .
products = (ShopItem.objects.filter(selectedproduct__order=order)
.annotate(quantity=Count('selectedproduct')))
如果有人需要类似的东西,我想我已经找到了解决方案:
quantity = ShopItem.objects.filter(
id=OuterRef("product_id"),
selectedproduct__order=order).annotate(
quantity=Count('selectedproduct')
).values_list("quantity", flat=True)
order.products.all().select_related("product").annotate(quantity=Subquery(quantity))
quantity
子查询接受带有 OuterRef
的产品 ID(商店商品 ID),并计算 order
的选定产品数量。我们使用 .values_list("quantity", flat=True)
来获得注释数量的固定值(因为 returned 结果是单个值)。例如,子查询将 return 值 3
,我们直接在主查询上使用它。
我正在尝试注释不同产品的数量,但到目前为止我还没有成功。我收到如下错误:
ProgrammingError: subquery must return only one column
LINE 1: ..._id", "shop_selectedproduct"."create_date", COUNT((SELECT U0...
我有以下型号:
class ShopItem(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
store = models.ForeignKey(to=Store, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
class SelectedProduct(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="products", null=True, blank=True)
product = models.ForeignKey(ShopItem, null=True, blank=True, on_delete=models.SET_NULL)
class Order(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
store = models.ForeignKey(Store, on_delete=models.CASCADE, related_name="orders")
status = models.PositiveIntegerField(choices=OrderStatus.choices, default=OrderStatus.CART)
number = models.CharField(max_length=36, blank=True, null=True)
我尝试计算不同的商品,例如 p1, p2, p3, p4 and p5
其中 p1 数量应该是 3,因为它被选择了三次,而其他人可能只有一个数量,因为我们只选择了每个产品中的一个。
我的原始实现:
products = order.products.all().annotate(quantity=Count("product"))
但是对于所有产品,这总是 returns 1,尽管它们被选择了多次。
我现在尝试解决这个问题是:
# order = 1
SelectedProduct.objects.filter(order=order).annotate(quantity=Count(Subquery(ShopItem.objects.filter(id=OuterRef("product")))))
无论如何我可以计算产品被选中的次数并在 selected_product 上注释,例如:
p1.quanity
> 3
p2.quanity
> 1
p3.quanity
> 1
p4.quanity
> 1
p5.quanity
> 1
如有任何见解,我将不胜感激。
编辑:我进一步的尝试:
subquery = Subquery(ShopItem.objects.filter(selectedproduct__order=order, selectedproduct=OuterRef('id')).order_by()
.values('selectedproduct').annotate(count=Count('pk'))
.values('count'), output_field=IntegerField())
SelectedProduct.objects.filter(order=order).annotate(child_count=Coalesce(Subquery, 0))
它抛出 RecursionError: maximum recursion depth exceeded
假设您在 per-order 基础上执行此操作,您可以从订单实例本身查询并在相关管理器上注释?
# Assuming the instance is self
self.products.all().annotate(
quantity=Count(
'product', distinct=True
),
)
试试这个:
SelectedProduct.objects.filter(
order=order
).values(
'product'
).annotate(
quantity=Count('product')
).order_by('product')
此外,您可以统计所有已选择产品的数据:
SelectedProduct.objects.values(
'product'
).annotate(
quantity=Count('product')
).order_by('product')
如果您想计算所有产品的所有选定项目
ShopItem.objects.annotate(
quantity=Count('selectedproduct')
)
更新 1
至returns相关对象字段
from django.db.models import F
SelectedProduct.objects.values(
'product'
).annotate(
quantity=Count('product'),
item_name = F('product__name'),
item_store = F('product__store'),
# also, you can use
#item_store_name= F('product__store__name'),
).order_by('product')
给定一个 order
实例,如果您想要该订单中的 ShopItem
的集合,并在订单中注释了它们的数量,您可以查询 ShopItem
table .
products = (ShopItem.objects.filter(selectedproduct__order=order)
.annotate(quantity=Count('selectedproduct')))
如果有人需要类似的东西,我想我已经找到了解决方案:
quantity = ShopItem.objects.filter(
id=OuterRef("product_id"),
selectedproduct__order=order).annotate(
quantity=Count('selectedproduct')
).values_list("quantity", flat=True)
order.products.all().select_related("product").annotate(quantity=Subquery(quantity))
quantity
子查询接受带有 OuterRef
的产品 ID(商店商品 ID),并计算 order
的选定产品数量。我们使用 .values_list("quantity", flat=True)
来获得注释数量的固定值(因为 returned 结果是单个值)。例如,子查询将 return 值 3
,我们直接在主查询上使用它。