这是sql数据库数据:
- UserTable
- UserName | UserDate | UserCode
- -------------------------------------------
- user1 | 08-31-2014 | 232
- user1 | 09-01-2014 | 232
- user1 | 09-02-2014 | 0
- user1 | 09-03-2014 | 121
- user1 | 09-08-2014 | 122
- user1 | 09-09-2014 | 0
- user1 | 09-10-2014 | 144
- user1 | 09-11-2014 | 166
- user2 | 09-01-2014 | 177
- user2 | 09-04-2014 | 188
- user2 | 09-05-2014 | 199
- user2 | 09-06-2014 | 0
- user2 | 09-07-2014 | 155
如果[UserCode]不是零,则应仅计算连续天数(如果为结果).
UserDate介于09-01-2014和09-11-2014之间.
仅在结果为2或更多时显示结果.
我希望我的SQL查询返回的是:
- UserName | StartDate | EndDate | Result
- ----------------------------------------------------------
- user1 | 09-01-2014 | 09-03-2014 | 2
- user1 | 09-08-2014 | 09-11-2014 | 3
- user2 | 09-04-2014 | 09-07-2014 | 3
这只能使用SQL查询吗?
解决方法
这是一个
Gaps and Islands问题.解决此问题的最简单方法是使用ROW_NUMBER()来识别序列中的间隙:
- SELECT UserName,UserDate,UserCode,GroupingSet = DATEADD(DAY,-ROW_NUMBER() OVER(PARTITION BY UserName
- ORDER BY UserDate),UserDate)
- FROM UserTable;
这给出了:
- UserName | UserDate | UserCode | GroupingSet
- ------------+---------------+------------+-------------
- user1 | 09-01-2014 | 1 | 08-31-2014
- user1 | 09-02-2014 | 0 | 08-31-2014
- user1 | 09-03-2014 | 1 | 08-31-2014
- user1 | 09-08-2014 | 1 | 09-04-2014
- user1 | 09-09-2014 | 0 | 09-04-2014
- user1 | 09-10-2014 | 1 | 09-04-2014
- user1 | 09-11-2014 | 1 | 09-04-2014
- user2 | 09-01-2014 | 1 | 08-31-2014
- user2 | 09-04-2014 | 1 | 09-02-2014
- user2 | 09-05-2014 | 1 | 09-02-2014
- user2 | 09-06-2014 | 0 | 09-02-2014
- user2 | 09-07-2014 | 1 | 09-02-2014
如您所见,这为连续行的GroupingSet提供了一个常量值.然后,您可以按此列分组以获取所需的摘要:
- WITH CTE AS
- ( SELECT UserName,-ROW_NUMBER() OVER(PARTITION BY UserName
- ORDER BY UserDate),UserDate)
- FROM UserTable
- )
- SELECT UserName,StartDate = MIN(UserDate),EndDate = MAX(UserDate),Result = COUNT(NULLIF(UserCode,0))
- FROM CTE
- GROUP BY UserName,GroupingSet
- HAVING COUNT(NULLIF(UserCode,0)) > 1
- ORDER BY UserName,StartDate;