2012-09-19 174 views
7

我有一個名爲Absence Details的表,我想將連續日期分組。這裏,是數據SQL Server查詢分組順序日期

EID  AbsenceType AbsenceStartDate    AbsenceEndDate 
769  Holiday  2012-06-25 00:00:00.000   2012-06-25 23:59:59.000 
769  Holiday  2012-06-26 00:00:00.000   2012-06-26 23:59:59.000 
769  Holiday  2012-09-03 00:00:00.000   2012-09-03 23:59:59.000 
769  Holiday  2012-09-04 00:00:00.000   2012-09-04 23:59:59.000 
769  Holiday  2012-09-05 00:00:00.000   2012-09-05 23:59:59.000 
769  Holiday  2012-09-06 00:00:00.000   2012-09-06 23:59:59.000 
769  Holiday  2012-09-07 00:00:00.000   2012-09-07 23:59:59.000 

我試圖得到的結果是

EID  AbsenceType AbsenceStartDate   AbsenceEndDate 
769  Holiday  2012-06-25 00:00:00.000   2012-06-26 23:59:59.000 
769  Holiday  2012-09-03 00:00:00.000   2012-09-07 23:59:59.000 

任何幫助深表感謝。

+0

您忘記了從標題中刪除AbsenceType列或爲此列添加值。 – Vikdor

+0

@ Vikdor - 這是真的,我忘了刪除缺席原因欄。感謝那。 – user1682461

+0

@podiluska - 我還沒有開始寫任何查詢。只是尋找指針。 – user1682461

回答

0

如果我正確理解你的問題,你想在你的記錄中找到連續的時間間隔。
主要的問題將確定究竟是什麼構成了連續的時間間隔:
如果你在工作中尋找沒有比

date1.09:00 to date1.18:00 
date2.09:00 to date2.18:00 

任何序列,其中date2是一個下一工作日date1可以考慮後連續。

在你的情況下,它是相對容易的,但你不能在一個單一的查詢。至少我現在想不出一種辦法。

P.S. 「podiluska」建議的「孤島和差距」算法將幫助您將其寫入單個查詢/存儲過程。

1

如下我會做到這一點:

  1. 確定沒有日期的順序列表。

    SELECT 
        ad1.EID, ad1.StartDate, ad2.EndDate 
    FROM 
        AbsenceDetails ad1 
        JOIN AbsenceDetails ad2 
        ON ad1.EID = ad2.EID 
    WHERE 
        DATEDIFF(ss, ad1.EndDate, ad2.StartDate) = 1 
    

    結果將是如下:通過列表

    769 2012-06-25 00:00:00.000 2012-06-26 23:59:59.000 
    769 2012-09-03 00:00:00.000 2012-09-04 23:59:59.000 
    769 2012-09-04 00:00:00.000 2012-09-05 23:59:59.000 
    769 2012-09-05 00:00:00.000 2012-09-06 23:59:59.000 
    769 2012-09-06 00:00:00.000 2012-09-07 23:59:59.000 
    
  2. 迭代和每個識別的伸展開始和結束時間。這最好在應用層完成。

4

我簡化了您的場景以隔離主要問題。讓我們supose此表差距:

with ns as (
select 1 as n union 
select 2 as n union 
select 3 as n union 
select 8 as n union --gap 
select 9 as n) 
select * 
into #ns 
from ns; 

現在,您所期待的結果是:

ini fi 
--- -- 
1 3 
8 9 

爲了得到這個結果我按摩的數據是這樣的:首先,我創建啓動兩個視圖結束期間和第二,我加入兩個觀點,以獲得最終結果。請注意,我與它自己一起定位開始和結束時段:

with 
inis as          -- identifying start periods 
(
    select n1.n 
    from #ns n1 
    left outer join #ns n2 
     on n1.n = n2.n + 1 
    where n2.n is null 
    ), 
fis as          -- identifying ends periods 
( 
    select n1.n 
    from #ns n1 
    left outer join #ns n2 
     on n1.n = n2.n - 1 
    where n2.n is null 
    ) 
select inis.n as ini, min(fis.n) as fi -- joining starts and ends 
from inis 
inner join fis 
    on inis.n <= fis.n 
group by inis.n 
; 

您可以將此技術轉移到您的數據和數據類型。如果您在翻譯查詢時有任何問題可以自由提問。

Check query and results.

4

這裏是爲我工作的解決方案。

SELECT EID, AbsenceType, MIN(AbsenceStartDate) AS AbsenceStartDate, MAX(AbsenceEndDate) AS AbsenceEndDate 
FROM (SELECT EID, AbsenceType, AbsenceStartDate, AbsenceEndDate, 
     DATEADD(dd, - ROW_NUMBER() OVER (PARTITION BY EID, AbsenceType ORDER BY EID,AbsenceStartDate), AbsenceStartDate) 
     FROM AbsenceDetails 
     GROUP BY EID,AbsenceType,AbsenceStartDate,AbsenceEndDate 
    ) a(EID, AbsenceType, AbsenceStartDate, AbsenceEndDate, Grp) 
GROUP BY EID, AbsenceType, Grp; 
+0

+1這是一個非常好的答案。下次請記住格式化代碼 –