SQL 计算连续天数

Posted

技术标签:

【中文标题】SQL 计算连续天数【英文标题】:SQL count consecutive days 【发布时间】:2014-09-30 09:22:37 【问题描述】:

这是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] 不是零,则应仅计算连续天数(作为结果)。 用户日期介于 09-01-2014 和 09-11-2014 之间。 仅当 Result 为 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 查询吗?

【问题讨论】:

你用的是什么版本的mssql? 【参考方案1】:

这是一个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,
            UserDate,
            UserCode,
            GroupingSet = DATEADD(DAY, 
                                -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;

Example on SQL Fiddle

【讨论】:

谢谢你,但我编辑了我的问题。我的错!我不能使用 sum,因为 UserCode 并不总是 1 或 0。 好的,我刚刚把SUM改成了COUNT(NULLIF(UserCode, 0)),所以当UserCode0NULLIF函数会把它变成NULL,就赢了'不包含在COUNT 这真是一个绝妙的解决方案??【参考方案2】:

请尝试:

;with T1 as(
    select 
        *, 
        ROW_NUMBER() over (  order by UserName, UserDate) ID 
    from tbl
)
,T as (
    SELECT *, 1 CNT FROM T1 where ID=1
    union all
    SELECT b.*, (case when T.UserDate+1=b.UserDate and 
                           T.UserName=b.UserName then t.CNT 
                        else T.CNT+1 end)
    from T1 b INNER JOIN T on b.ID=T.ID+1
)
select distinct UserName, MIN(UserDate), max(UserDate)
,sum(case UserCode when 0 then 0 else 1 end) From T group by UserName, CNT
having COUNT(*)>1

SQL Fiddle Demo

【讨论】:

谢谢你,但我编辑了我的问题。我的错!我不能使用 sum,因为 UserCode 并不总是 1 或 0。

以上是关于SQL 计算连续天数的主要内容,如果未能解决你的问题,请参考以下文章

SQL 计算连续天数

SQL 计算最长连续登录天数

sql 连续活跃天数

spark sql 连续登录最大天数

Hive计算最大连续登陆天数

SQL经典问题 找出连续日期及连续的天数