2014-01-29 27 views
0

使用SQL Server,我怎麼產生的結果集,顯示日期的範圍,像這樣的:使用T-SQL,我怎麼產生的結果,顯示日期範圍

StartDate EndDate 
01/01/2014 01/04/2014 
01/08/2014 01/11/2014 
01/14/2014 01/15/2014 

原數據曾在此格式中的日期:

ColumnA  DateColumn 
blah   01/01/2014 
blah   01/02/2014 
blah   01/03/2014 
blah   01/04/2014 
blah   01/08/2014 
blah   01/09/2014 
blah   01/10/2014 
blah   01/11/2014 
blah   01/14/2014 
blah   01/15/2014 

目前,我有一堆,這是否查詢,但我想知道如果我能在更少的代碼做一些事情:

SELECT ROW_NUMBER() OVER(ORDER BY DateColumn) AS rownum, 
     DateColumn 
INTO #main 
FROM MyTable 

SELECT m1.DateColumn AS TBegin, 
     m2.DateColumn AS TEnd, 
     COALESCE(DATEDIFF(day, m2.TimePk, m1.TimePk), 0) AS Gap 
INTO #Gap 
FROM #main m1 
LEFT OUTER JOIN #main m2 
ON m1.rownum = m2.rownum + 1 
ORDER BY m1.DateColumn 

SELECT ROW_NUMBER() OVER(ORDER BY i_id, TBegin) AS rownum, 
     TBegin 
INTO #Begin 
FROM #Gap 
WHERE Gap <> 1 
ORDER BY TBegin 

SELECT ROW_NUMBER() OVER(ORDER BY i_id, TEnd) AS rownum, 
     TEnd 
INTO #End 
FROM (
    SELECT TEnd 
    FROM #Gap 
    WHERE Gap > 1 
    UNION 
    SELECT MAX(TBegin) 
    FROM #Gap 
    ) as t 
ORDER BY TEnd 

SELECT b.TBegin, 
     e.TEnd 
FROM #Begin b 
INNER JOIN #End e 
     ON b.i_id = e.i_id 
     AND b.rownum = e.rownum 
ORDER BY b.TBegin 

關於如何以完全不同的方式簡化或處理此問題的任何想法?

回答

0

我對這些方法的做法是確定沒有日期的第一個日期。這是一個團體的開始。然後我把這個累計和作爲一個組標識符,並進行聚合。

SQL Server 2008中沒有lag或累計總和,所以我用相關子查詢此:

with mt as (
     select t.*, 
      (case when (select top 1 t2.dateColumn 
         from MyTable t2 
         where t2.ColumnA = t.ColumnA and 
           t2.dateColumn < t.dateColumn 
         order by t2.dateColumn desc 
         ) = dateadd(day, -1, t.datecolumn) 
        then 0 
        else 1 
       end) as IsStart 
     from MyTable t 
    ), 
    mtcum as (
     select mt.*, 
      (select sum(mt2.IsStart) 
       from mt mt2 
       where mt2.ColumnA = mt.ColumnA and 
        mt2.dateColumn <= mt.DateColumn 
      ) as grpId 
     from mt 
    ) 
select ColumnA, min(dateColumn) as StartDate, max(dateColumn) as EndDate 
from mtcum 
group by ColumnA, grpId; 

編輯:

的方法更簡單的方法,這是與觀察到的差異日期序列和數字序列之間的關係是恆定的。

select columnA, min(dateColumn) as StartDate, max(dateColumn) as EndDate 
from (select mt.*, row_number() over (partition by ColumnA order by datecolumn) as seqnum 
     from mytable mt 
    ) t 
group by columnA, dateadd(day, - seqnum, datecolumn); 
0

這將爲你工作。儘管如此,它仍然相當複雜。它使用內部查詢來查找每個日期之後的第一個日期。這樣,屬於同一組日期的所有日子都可以組合在一起。

select MIN(DateColumn) StartDate, MAX(DateColumn) EndDate from 
    (select X.DateColumn, MIN(Y.DateColumn) MinOverGap from 
     (select DateColumn, ROW_NUMBER() OVER (ORDER BY DateColumn) RowNumber 
     from MyTable) X 
    left join 
     (select DateColumn, ROW_NUMBER() OVER (ORDER BY DateColumn) RowNumber 
     from MyTable) Y 
     on DATEADD(d, Y.RowNumber - 1, X.DateColumn) <> DATEADD(d, X.RowNumber -1, Y.DateColumn) AND X.DateColumn < Y.DateColumn 
    group by x.DateColumn) grouped 
group by MinOverGap 
order by 1