2016-04-01 13 views
2

Bir tarihin, bir ayın başlangıcındaki haftanın gününe ve tarihine göre hesaplamak istiyorum. Bir @StartDate = 2016/04/01 ve @EndDate = 2016/09/01 sahip varsayarsak, ben her ayın ilk Cuma herkes için tarihleri ​​yaratacak @EndDate sonra, Nisan ayının ilk Cuma günü @StartDate olduğunu kontrol edin:Günün tarihine ve ayın başlangıcına göre tarih hazinesi oluşturun

durumda @StartDate = 2016/04/12 ve @EndDate = 2016/09/01 yılında
2016/05/06 
2016/06/03 
2016/07/01 
2016/08/05 

, ben dikkat durumda @StartDate = 2016/04/28 ve @EndDate = 2016/09/01 yılında

2016/05/10 
2016/06/14 
2016/07/12 
2016/08/09 

, ben @StartDate l üzerinde olduğuna dikkat: @StartDate Nisan ayının ikinci Salı, daha sonra her ayın ikinci Salı günü Salı almaya gitti Nisan ayının ast Perşembe: Sadece 4 hafta ya da 5 hafta ile aylar bulunduğundan son durumda

2016/05/26 
2016/06/30 
2016/07/28 
2016/08/25 

, ben her ayın hafta numarasını doğrulamak gerekir ve ben son örneğini istiyorum.

Ne yaptım? Ben ayın üçüncü haftasında beni her Pazartesi veren bir kod buldum ve ben bir @StartDate ve @EndDate almak için biraz benimsenen: Yani

;with 
filler as (select row_number() over (order by a) a from (select top 100 1 as a from syscolumns) a cross join (select top 100 1 as b from syscolumns) b), 
dates as (select dateadd(month, a-1, @StartDate) date from filler where a <= 1000 and dateadd(month, a-1, @StartDate) < @EndDate), 
FirstMonday as (
select dateadd(day, case datepart(weekday,Date) /*this is the case where verify the week day*/ 
          when 1 then 1 
          when 2 then 0 
          when 3 then 6 
          when 4 then 5 
          when 5 then 4 
          when 6 then 3 
          when 7 then 2 
         end, Date) as Date 
     ,case when datepart(weekday, @StartDate) = 1 then 3 else 2 end as Weeks /*here i verify the number of weeks to sum in the next date*/ 
from dates 
) 
select dateadd(week, Weeks, Date) as ThirdMonday 
from FirstMonday 
+0

Kurallarınızda belirsizdir. Bir ayın dördüncü pazartesi ile son pazartesi arasındaki farkı nasıl ayırt edersiniz? –

+0

@GordonLinoff kod hakkında konuşuyorsunuz? Bunu yapmak için uyarlamalıyım – CesarMiguel

+1

Bir [takvim tablosu] kullanmayı düşündünüz mü (https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql -sunucu /)? Tüm tarihlerin tam bir listesinden, hafta içi ve hafta numaraları dahil olmak üzere, her zaman ihtiyacınız olan tarihleri ​​filtreleyebilirsiniz. –

cevap

2

, öyle:

set @NumSemana = datepart(day, datediff(day, DATEADD(mm, DATEDIFF(mm,0,@StartDate), 0), @StartDate)/7 * 7)/7 + 1; 
WITH AllDays 
    AS (SELECT @StartDate AS [Date], DATEPART(month, @StartDate) as validMonth 
     UNION ALL 
     SELECT DATEADD(week, 1, [Date]), 
       iif(DATEPART(month,DATEADD(week, 1, [Date])) < validMonth + @PeriodicityRepeat, validMonth, validMonth + @PeriodicityRepeat) 
     FROM  AllDays 
     WHERE  
      DATEPART(month,[Date]) <= DATEPART(month,@EndDate) 
     and DATEPART(year,[Date]) <= DATEPART(year,@EndDate) 
      ), 
rankedDays 
    AS(  
    SELECT [Date], validMonth, 
      row_number() over (partition by DATEPART(month, [Date]) order by [Date]) ascOrder, 
      row_number() over (partition by DATEPART(month, [Date]) order by [Date] desc) descOrder 
    FROM AllDays 
    WHERE DATEPART(month, [Date]) = validMonth 
) 
select [Date] 
from rankedDays 
where ((ascOrder = @NumSemana and @NumSemana <=4) 
     or (descOrder = 1 and @NumSemana = 5) 
     or [Date] = @StartDate) 
    and [Date] < @EndDate 
OPTION (MAXRECURSION 0) 
1

Sorgu:

DECLARE @StartDate DATE = '2016-04-28', 
     @EndDate DATE = '2016-09-01' 

;WITH dates AS (
SELECT DATEADD(week, -5, @StartDate) as date_ 
UNION ALL 
SELECT DATEADD(week,1,date_) 
FROM dates 
WHERE DATEADD(week,1,date_) < @enddate 
), final AS (
SELECT ROW_NUMBER() OVER (PARTITION BY DATEPART(year,date_), DATEPART(month,date_) ORDER BY date_ ASC) as RN, 
     date_ 
FROM dates 
), weeks AS (
SELECT * 
FROM (VALUES 
(1,1), 
(2,2), 
(3,3), 
(4,4), 
(4,5), 
(5,4), 
(5,5) 
) as t(w1,w2) 
WHERE w1 = (SELECT RN FROM final WHERE date_ = @StartDate) 
) 


SELECT MAX(date_) as date_ 
FROM final f 
INNER JOIN weeks w ON f.RN = w.w2 
WHERE date_ between @StartDate and @EndDate AND date_ != @StartDate 
GROUP BY DATEPART(YEAR,date_), DATEPART(MONTH,date_) 
ORDER BY MAX(date_) ASC 

Çıkışlar:

@StartDate = 2016/04/01 için

ve

date_ 
---------- 
2016-05-06 
2016-06-03 
2016-07-01 
2016-08-05 

(4 row(s) affected) 

@EndDate = 2016/09/01@StartDate = 2016/04/12 için ve

date_ 
---------- 
2016-05-10 
2016-06-14 
2016-07-12 
2016-08-09 

(4 row(s) affected) 

@EndDate = 2016/09/01@StartDate = 2016/04/28 için ve @EndDate = 2016/09/01

date_ 
---------- 
2016-05-26 
2016-06-30 
2016-07-28 
2016-08-25 

(4 row(s) affected) 
+0

da çalışıyor! +1 – CesarMiguel

İlgili konular