Django: คำนวณผลรวมของค่าคอลัมน์ผ่านแบบสอบถาม


93

ฉันมีแบบจำลอง

class ItemPrice( models.Model ):
     price = models.DecimalField ( max_digits = 8, decimal_places=2 )
     ....

ฉันลองสิ่งนี้เพื่อคำนวณผลรวมของpriceชุดแบบสอบถามนี้:

items = ItemPrice.objects.all().annotate(Sum('price'))

คำถามนี้มีอะไรผิดพลาด หรือมีวิธีอื่นในการคำนวณผลรวมของpriceคอลัมน์หรือไม่?

ฉันรู้ว่าสิ่งนี้สามารถทำได้โดยใช้สำหรับ loop บน queryset แต่ฉันต้องการโซลูชันที่สวยงาม

ขอบคุณ!


สิ่งนี้ตอบคำถามของคุณหรือไม่? แบบสอบถาม Django SUM?
Flimm

คำตอบ:


197

คุณอาจกำลังมองหา aggregate

from django.db.models import Sum

ItemPrice.objects.aggregate(Sum('price'))
# returns {'price__sum': 1000} for example

1
ฉันจะนับรวมที่มีราคา = 5000 ได้อย่างไร
Anuj Sharma

6
โปรดจำไว้ว่าผลตอบแทนพจนานุกรมไม่ลอย / {'price__sum':1000}จำนวนเต็มเช่น สามารถรับจำนวนลอย / จำนวนเต็มด้วยyourdict['price__sum']
Josh

35

คำอธิบายประกอบเพิ่มเขตข้อมูลในผลลัพธ์:

>> Order.objects.annotate(total_price=Sum('price'))
<QuerySet [<Order: L-555>, <Order: L-222>]>

>> orders.first().total_price
Decimal('340.00')

ผลรวมส่งคืนคำสั่งพร้อมผลลัพธ์ที่ถาม:

>> Order.objects.aggregate(total_price=Sum('price'))
{'total_price': Decimal('1260.00')}

ผมขอขอบคุณที่คุณแสดงให้เห็นว่าการระบุkeyในการจัดเก็บรวมvalueเข้า
MikeyE


5

ใช้cProfile Profilerผมพบว่าในการพัฒนาสภาพแวดล้อมของฉันมันมีประสิทธิภาพมากขึ้น (เร็วกว่า) Sum()จะสรุปค่าของรายการมากกว่าที่จะรวมการใช้ เช่น:

sum_a = sum([item.column for item in queryset]) # Definitely takes more memory.
sum_b = queryset.aggregate(Sum('column')).get('column__sum') # Takes about 20% more time.

ฉันทดสอบสิ่งนี้ในบริบทที่แตกต่างกันและดูเหมือนว่าการใช้aggregateจะใช้เวลานานกว่าเสมอเพื่อให้ได้ผลลัพธ์เดียวกัน แม้ว่าฉันสงสัยว่าอาจมีข้อดีที่ควรใช้หน่วยความจำแทนการสรุปรายการ


1
sum_a = sum(item.column for item in queryset)หรือใช้การแสดงออกเครื่องกำเนิดไฟฟ้าแทนของรายการ: ข้อแตกต่างเพียงอย่างเดียวคือ[]s ที่ถูกลบออก ซึ่งจะช่วยประหยัดพื้นที่หน่วยความจำสำหรับการคำนวณรายการทั้งหมดก่อนที่จะsum()วนซ้ำ
Code-Apprentice
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.