SQL Server中按特定条件分区使用Min()与Max()函数的技术问询
解决SQL Server中按连续Category分区计算极值的问题
嘿,我完全懂你的需求——你不想把所有同Category的记录混在一起算Min/Max,而是要按连续出现的Category分组来统计,就像测试数据里前5条c1是一个连续组,接着的5条c2是一组,最后那条单独的c1又是独立的一组,分别算出每个连续组的最早和最晚时间戳。
实现思路
这里我们可以用SQL Server的窗口函数来识别连续分组,核心分两步走:
- 用
LAG()函数对比当前行和上一行的Category,标记出分组变化的位置 - 对这些变化标记做累计求和,生成唯一的连续分组ID,最后按这个ID+Category分组计算极值
完整可运行代码
-- 先创建测试表并插入数据 Create Table #Test (Id Int Identity(1,1), Category Varchar(100), DateTimeStamp DateTime) Insert into #Test (Category,DateTimeStamp) values ('c1','2019-08-13 01:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c1','2019-08-13 02:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c1','2019-08-13 03:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c1','2019-08-13 04:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c1','2019-08-13 05:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c2','2019-08-13 06:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c2','2019-08-13 07:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c2','2019-08-13 08:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c2','2019-08-13 09:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c2','2019-08-13 10:00:13.503') Insert into #Test (Category,DateTimeStamp) values ('c1','2019-08-13 11:00:13.503') -- 核心查询:计算连续分组的Min/Max时间戳 WITH ContinuousGroups AS ( SELECT Category, DateTimeStamp, -- 标记分组变化:当前Category和上一行不同时记为1,否则0 CASE WHEN LAG(Category) OVER (ORDER BY Id) != Category THEN 1 ELSE 0 END AS GroupChange, Id FROM #Test ), GroupedData AS ( SELECT Category, DateTimeStamp, -- 累计求和生成唯一的连续分组ID SUM(GroupChange) OVER (ORDER BY Id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS GroupId FROM ContinuousGroups ) SELECT Category, MIN(DateTimeStamp) AS minn, MAX(DateTimeStamp) AS maxx FROM GroupedData GROUP BY GroupId, Category ORDER BY MIN(Id); -- 按分组的最早记录ID排序,保证结果顺序符合数据顺序 -- 清理临时表 DROP TABLE #Test;
运行结果
执行后会得到你想要的结果:
| Category | minn | maxx |
|---|---|---|
| c1 | 2019-08-13 01:00:13.503 | 2019-08-13 05:00:13.503 |
| c2 | 2019-08-13 06:00:13.503 | 2019-08-13 10:00:13.503 |
| c1 | 2019-08-13 11:00:13.503 | 2019-08-13 11:00:13.503 |
这样就精准实现了按连续Category分区计算极值的需求,每个连续的同Category组都被单独统计了最早和最晚时间戳。
内容的提问来源于stack exchange,提问作者Hardik Parmar
相关产品推荐
相关产品推荐

