2013-11-28 44 views
5

Ben ben neden istiyoruz "FROM_DATE" ve "to_date"Bölünmüş tarih aralığı

the table look like:- 

enter image description here

olarak adlandırılan iki sütun ile bir tablo gibi: -

from_date   to_date 
-----------   ------------ 
2013-11-25   2013-11-30 
2013-12-01   2013-12-05 

Bu tarih 2013-11-25'ten 2013-11-30'a kadar olan bölümler ve 2013-12-01'den 2013-12-05'e kadar başka bir tarih ayrılmıştır ... Bu şekilde bölünmek mümkün mü?

+1

Aşağıdakiler * neredeyse * aynıdır. Yalnızca tam aylar için çalışır, ancak kısmi aylarda da çalışmasını değiştirmek için önemsiz olmalıdır: http://stackoverflow.com/questions/7218526/split-date-range-into-months – Heinzi

+0

Tarihler 3 ay arasındaysa Örneğin 2013-11-25'ten 2014-02-05'e bu 3 sıraya veya 4'e bölünmeli mi? – GarethD

cevap

5

Bu, geçen yıl güvenlidir ve şu andaki diğer yanıtların tarih aralığını kullanır.

DECLARE @d TABLE(from_date DATE, to_date DATE); 

INSERT @d VALUES ('2013-11-25','2013-12-05'); 

;WITH n(n) AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY [object_id])-1 FROM sys.all_columns 
), 
d(n,f,t,md,bp,ep) AS 
(
    SELECT n.n, d.from_date, d.to_date, 
    DATEDIFF(MONTH, d.from_date, d.to_date), 
    DATEADD(MONTH, n.n, DATEADD(DAY, 1-DAY(from_date), from_date)), 
    DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, n.n, 
     DATEADD(DAY, 1-DAY(from_date), from_date)))) 
FROM n INNER JOIN @d AS d 
ON d.to_date >= DATEADD(MONTH, n.n-1, d.from_date) 
) 
SELECT original_from_date = f, original_to_date = t, 
    new_from_date = CASE n WHEN 0 THEN f ELSE bp END, 
    new_to_date = CASE n WHEN md THEN t ELSE ep END 
FROM d WHERE md >= n 
ORDER BY original_from_date, new_from_date; 

Sonuçlar:

original_from_date original_to_date new_from_date new_to_date 
------------------ ---------------- ------------- ----------- 
2013-11-25   2013-12-05   2013-11-25  2013-11-30 
2013-11-25   2013-12-05   2013-12-01  2013-12-05 

SQLFiddle demo with longer date ranges and leap years

+0

İstediğim şey ... Sorgunun iyi çalıştığı @Aaron Bertrand. –

+0

İlk başlangıç_tarihi, 31 günden daha kısa bir ayı izleyen bir ay boyunca olursa, çözümünüz ayın son gününü doğru olarak bulamaz. Kasım'dan ziyade Ekim ile başlayın. Ekim ayı Eylül ve Eylül ayları 31 günden azdır. – Kennah

+0

Bunu bulamadım. Martijn Vermunt yaptı. http://stackoverflow.com/q/34514361/2471473 – Kennah

1

Bir boyutlu veri ambarında faaliyet yapıyorsanız, tarih boyutunu kullanmaktadır. Aksi takdirde, CTE kullanın.

WITH cte AS 
(SELECT from_date 
     , to_date 
     , from_date AS mo_from_date 
     , DATEADD(day, day(from_date)* -1 + 1, from_date) AS bom_date 
    FROM DateTable 
UNION ALL 
SELECT from_date 
    , to_date 
    , DATEADD(month,1,bom_date) 
    , DATEADD(month,1,bom_date) 
    FROM cte 
where DATEADD(month,1,mo_from_date) < to_date 
) 
SELECT mo_from_date 
    , CASE when to_date < DATEADD(month,1,bom_date) THEN 
      to_date 
     ELSE 
      DATEADD(day, -1, DATEADD(month,1,bom_date)) 
     END AS mo_to_date 
    FROM cte 
İlgili konular