如何在MongoDB中按周六至周五的非标准周进行聚合统计?
按周六到周五的非标准周统计员工总工时
嘿,这个需求我之前碰到过!MongoDB默认的周起始是周日或周一(取决于版本和配置),要实现周六开始、周五结束的周统计,核心就是手动调整日期的分组依据,把同一周的所有日期映射到同一个起始点(也就是当周的周六),然后再分组求和就行。
完整聚合查询代码
db.myCollection.aggregate([ // 第一步:过滤目标员工,可按需添加日期范围过滤 { $match: { Employee: "Bill" } }, // 第二步:计算每条记录所属的「周六起始周」的周六日期 { $addFields: { weekStart: { $dateSubtract: { startDate: "$Date", unit: "day", amount: { $cond: { if: { $eq: [ { $dayOfWeek: "$Date" }, 7 ] }, // MongoDB中$dayOfWeek返回7代表周六 then: 0, // 当天就是周六,无需偏移 else: { $subtract: [ { $dayOfWeek: "$Date" }, 1 ] } // 周日减1天、周一减2天...直到周五减6天,回到上一个周六 } } } } } }, // 第三步:按员工+周起始日期分组,统计总工时 { $group: { _id: { Employee: "$Employee", weekStart: "$weekStart" }, totalHours: { $sum: "$Hours" } } }, // 可选:按周起始日期排序,让结果更直观 { $sort: { "_id.weekStart": 1 } } ])
关键步骤解释
- $match阶段:和你熟悉的标准写法一样,先过滤出目标员工的记录,也可以在这里加上
Date的范围条件,减少后续计算的数据量。 - $addFields阶段:这是实现非标准周的核心。MongoDB的
$dayOfWeek函数会返回1(周日)到7(周六)的数值,我们通过条件判断:- 如果当前日期是周六,直接保留当天作为周起始点;
- 如果是周日到周五,减去对应的天数(周日减1天、周一减2天...),把日期偏移到上一个周六,这样同一周(周六到周五)的所有日期都会映射到同一个周六。
- $group阶段:按员工和周起始日期分组,用
$sum累加该周的工时总数。 - $sort阶段:可选步骤,让结果按周的时间顺序排列,方便查看。
扩展:显示周结束日期(周五)
如果需要在结果中明确显示周的结束日期(周五),可以在$addFields阶段添加一个weekEnd字段:
$addFields: { weekStart: { /* 上面的代码 */ }, weekEnd: { $dateAdd: { startDate: "$weekStart", unit: "day", amount: 6 } } }
这样分组后的结果里就能看到完整的「周六-周五」区间了。
内容的提问来源于stack exchange,提问作者Abe Miessler
相关产品推荐
相关产品推荐

