SQL count consecutive days

前端 未结 2 1930
孤独总比滥情好
孤独总比滥情好 2020-12-08 05:55

This is the SQL database data:

UserTable

UserName    | UserDate      | UserCode
-------------------------------------------
user1       | 08-31-2014    | 23         


        
相关标签:
2条回答
  • 2020-12-08 06:27

    This is a Gaps and Islands problem. The easiest way to solve this is using ROW_NUMBER() to identify the gaps in the sequence:

    SELECT  UserName,
            UserDate,
            UserCode,
            GroupingSet = DATEADD(DAY, 
                                -ROW_NUMBER() OVER(PARTITION BY UserName 
                                                            ORDER BY UserDate), 
                                UserDate)
    FROM    UserTable;
    

    This gives:

    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    
    

    As you can see this gives a constant value in GroupingSet for consecutive rows. You can then group by this colum to get the summary you want:

    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

    0 讨论(0)
  • 2020-12-08 06:30

    Please try:

    ;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

    0 讨论(0)
提交回复
热议问题