按12小时班次分组,查询各班次记录数最多的用户
解决12小时班次内记录数最多用户的SQL查询方案
刚好之前处理过类似的班次统计需求,给你分享一个可行的SQL方案,咱们一步步拆解问题:
第一步:把记录归类到对应的12小时班次
因为你的班次是从7:30而非整点分界,得先把每条记录的DateTime映射到所属班次的起始时间:
- 7:30AM到7:30PM的班次,起始时间是当天的
07:30:00 - 7:30PM到次日7:30AM的班次,起始时间是当天的
19:30:00(如果记录时间在次日0:00-7:30,就归到前一天的19:30班次)
第二步:统计每个用户在各班次的记录数
用CTE(公共表表达式)先完成班次归类和计数,再用窗口函数找出每个班次的Top用户。这里以MySQL为例,其他数据库(比如SQL Server、PostgreSQL)逻辑一致,只是函数语法稍有差异:
WITH Shift_User_Counts AS ( SELECT -- 确定每条记录所属的班次起始时间 CASE WHEN TIME(DateTime) >= '07:30:00' AND TIME(DateTime) < '19:30:00' THEN DATE_FORMAT(DateTime, '%Y-%m-%d 07:30:00') ELSE DATE_FORMAT( IF(TIME(DateTime) < '07:30:00', DATE_SUB(DateTime, INTERVAL 1 DAY), DateTime), '%Y-%m-%d 19:30:00' ) END AS Shift_Start, UserName, COUNT(*) AS Record_Count FROM your_table_name -- 替换成你的实际表名 GROUP BY Shift_Start, UserName ), Ranked_Users AS ( SELECT Shift_Start, UserName, Record_Count, -- 按班次分组,给用户按记录数降序排名 ROW_NUMBER() OVER (PARTITION BY Shift_Start ORDER BY Record_Count DESC) AS Rank FROM Shift_User_Counts ) SELECT Shift_Start, DATE_ADD(Shift_Start, INTERVAL 12 HOUR) AS Shift_End, -- 计算班次结束时间 UserName AS Top_User, Record_Count AS Max_Records FROM Ranked_Users WHERE Rank = 1;
特殊情况处理:并列第一的用户
如果同一个班次有多个用户记录数相同且都是最多的,ROW_NUMBER()只会返回其中一个。要是想把所有并列第一的用户都列出来,把ROW_NUMBER()换成RANK()或者DENSE_RANK()即可,再筛选Rank = 1就行。
用你的测试数据验证
拿你提供的测试数据跑这个查询,会得到以下结果:
| Shift_Start | Shift_End | Top_User | Max_Records |
|---|---|---|---|
| 2017-01-01 07:30:00 | 2017-01-01 19:30:00 | User1 | 2 |
| 2017-01-01 19:30:00 | 2017-01-02 07:30:00 | User2 | 2 |
完全符合预期对吧?如果用的是其他数据库,比如SQL Server,把DATE_FORMAT换成FORMAT或CONVERT,DATE_SUB换成DATEADD(day, -1, DateTime)就能适配了~
内容的提问来源于stack exchange,提问作者childsy
相关产品推荐
相关产品推荐

