คำนวณ Mean Daily Average Count ด้วย $group และ $project
ใช้ $match กรองวันที่, $group หาวันแรกสุดและผลรวม, $project คำนวณค่าเฉลี่ยต่อวันจากช่วงเวลาทั้งหมด
ตัวอย่างข้อมูล
> db.demo451.insertOne({ DueDate: new ISODate("2020-03-15T10:50:35.000Z"), Value: 10 });
> db.demo451.insertOne({ DueDate: new ISODate("2020-03-14T10:50:35.000Z"), Value: 10 });
> db.demo451.insertOne({ DueDate: new ISODate("2020-03-13T10:50:35.000Z"), Value: 10 });
Query คำนวณค่าเฉลี่ยรายวัน
> db.demo451.aggregate([
{ $match: { DueDate: { $lt: new ISODate() } } },
{ $group: {
_id: null,
olderDate: { $min: "$DueDate" },
sumValue: { $sum: "$Value" }
}},
{ $project: {
_id: 0,
averageValue: {
$divide: [
"$sumValue",
{ $divide: [{ $subtract: [new ISODate(), "$olderDate"] }, 1000 * 60 * 60 * 24] }
]
}
}}
]);
ผลลัพธ์
{ "averageValue": 2.475558456547562 }
คำอธิบายสูตร
Average per day = Total Value ÷ Number of days
sumValue- ผลรวม Value ทั้งหมด (30)olderDate- วันที่เก่าสุดในข้อมูลnew ISODate() - olderDate- มิลลิวินาทีของช่วงเวลา÷ (1000*60*60*24)- แปลงเป็นวันsumValue ÷ days- ค่าเฉลี่ยต่อวัน
กรณีใช้จริง (Production)
// ใช้ $dateToString จัดกลุ่มตามวัน แล้ว $avg
db.demo451.aggregate([
{ $match: { DueDate: { $lt: new ISODate() } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$DueDate" } }, dailySum: { $sum: "$Value" } } },
{ $group: { _id: null, averageDaily: { $avg: "$dailySum" } } }
]);
วิธีนี้แม่นยำกว่าเพราะคำนวณจากจำนวนวันจริงที่มีข้อมูล ไม่ใช่วันนับจากวันแรกสุด