2014-09-30 43 views
2

這是SQL數據庫的數據: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。 只有結果爲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查詢?

+1

什麼版本的MSSQL您使用的是? – Arion 2014-09-30 09:26:19

回答

10

這是一個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

+0

謝謝你,但我編輯了我的問題。我的錯!我無法使用sum,因爲UserCode並不總是隻有1或0. – majukivi 2014-09-30 10:17:31

+0

好吧,我剛剛將它從'SUM'更改爲COUNT(NULLIF(UserCode,0))',所以當'UserCode'爲'0' ,'NULLIF'函數會將它變成'NULL',並且它不會被包含在'COUNT'中。 – GarethD 2014-09-30 10:26:12

+0

謝謝。做得好!!! – majukivi 2014-09-30 10:48:40

0

請嘗試:

;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

謝謝你,但我編輯了我的問題。我的錯!我無法使用總和,因爲UserCode並不總是隻有1或0。 – majukivi 2014-09-30 10:17:03