如何在MongoDB中按渠道分组统计当年与上一年的营收、销量对应数值
MongoDB 按渠道统计当年及上一年营收销量聚合方案
前提说明:以下示例以统计2021年作为当前年为例,和你给出的预期输出逻辑匹配,如果需要调整统计年份,修改对应过滤条件和取值判断即可。
完整聚合查询语句
db.collection.aggregate([ // 1. 提取日期年份,补全缺失的quantity字段默认值为0 { $addFields: { year: { $toInt: { $substrCP: ["$date", 0, 4] } }, quantity: { $ifNull: ["$quantity", 0] } } }, // 2. 过滤只保留当前年、上一年数据,减少无效计算 { $match: { year: { $in: [2020, 2021] } } }, // 3. 按渠道+年份分组,统计单年单渠道的总营收、总销量 { $group: { _id: { channel: "$channel", year: "$year" }, total_revenue: { $sum: "$revenue" }, total_quantity: { $sum: "$quantity" } } }, // 4. 按渠道二次分组,把同渠道两年的统计结果聚合到同一文档 { $group: { _id: "$_id.channel", year_stats: { $push: { k: { $toString: "$_id.year" }, v: { revenue: "$total_revenue", quantity: "$total_quantity" } } } } }, // 5. 把年份统计数组转成键值对对象,方便后续取值 { $replaceRoot: { newRoot: { $mergeObjects: [ { channel: "$_id" }, { $arrayToObject: "$year_stats" } ] } } }, // 6. 映射为目标输出格式,缺失年份数据默认补0 { $project: { _id: 0, channel: 1, current_year_revenue: { $ifNull: ["$2021.revenue", 0] }, prev_year_revenue: { $ifNull: ["$2020.revenue", 0] }, current_year_quantity: { $ifNull: ["$2021.quantity", 0] }, prev_year_quantity: { $ifNull: ["$2020.quantity", 0] } } } ])
兼容说明
如果你的date字段存储的是MongoDB原生ISODate类型而非字符串,把第一步提取year的逻辑替换为year: { $year: "$date" }即可。
如果需要动态统计任意年份的同比数据,聚合前传入参数替换2021、2020的硬编码值即可。
内容的提问来源于stack exchange,提问作者khateeb
相关产品推荐
相关产品推荐

