Delphi Can

Orjinalini görmek için tıklayınız: Tarihin ayın kaçıncı haftası olduğu nasıl bulunur (Çözüldü)
Şu anda (Arşiv) modunu görüntülemektesiniz. Orjinal Sürümü Görüntüle internal link
Selamlar

Aşağıdaki şekilde bir sorgunun sonucunda en sonda bulunan X alanında 
Her ayın kendi içindeki hafta numarasını almaya çalışıyorum.
Fakat doğru sonuca ulaşamadım.

Doğru sonuç örneği aşağıdaki şekilde olmalıdır
01      Ocak 1.Hafta
02-08 Ocak 2.Hafta
09-15 Ocak 3.Hafta
16-22 Ocak 4.Hafta
23-29 Ocak 5.Hafta
30-31 Ocak 6.Hafta
----
01-05 Şubat 1.Hafta
06-12 Şubat 2.Hafta
.....

    
   Set DateFormat dmy
   Declare @Gunler Table (Tarih DateTime)
   Declare @Tarih DateTime
   Declare @BasTarih DateTime
   Declare @BitTarih DateTime

   Set @BasTarih = Cast('20230101' As DateTime)
   Set @BitTarih = Cast('20230330' As DateTime)

   Set @Tarih = @BasTarih
   While @Tarih <= @BitTarih 
   begin
       Insert Into @Gunler (Tarih)
       Values (@Tarih)
       Set @Tarih = DateAdd(Day, 1, @Tarih)
   End

   Set DateFirst 1
   Select T.*,
       ROW_NUMBER() OVER(PARTITION BY Yil, Ay, HaftaGun  ORDER BY Yil, Ay, YilHafta) As X
   From (
           Select G.Tarih, 
               DateName(Weekday, G.Tarih) As Gun,  
               DatePart(Year, G.Tarih) As Yil, 
               DatePart(Month, G.Tarih) As Ay, 
               DatePart(Week, G.Tarih) As YilHafta,
               DatePart(Weekday,G.Tarih) As HaftaGun
           From @Gunler G
       ) T
   Order By T.Tarih 

Aşağıdaki 2 farklı yöntemle çözümlenmiştir.

    
Set DateFormat dmy
    Set DateFirst 1

   Declare @Gunler Table 
       (   Tarih DateTime, sGun Varchar(10), sAy Varchar(10), Yil int, Ay int, Gun int, YilHafta int, HaftaGun int, 
           AyHaftaYontem1 int, AyHaftaYontem2 int, 
           TatilSekli TinyInt /* TatilSekli:0=Normal Çalışma, 1=Tam Gün Tatil, 2=Yarim Gün Tatil */
       )

   Declare @Tarih DateTime
   Declare @BasTarih DateTime
   Declare @BitTarih DateTime

   Set @BasTarih = Cast('20230101' As DateTime)
   Set @BitTarih = Cast('20231231' As DateTime)

   Set @Tarih = @BasTarih
   While @Tarih <= @BitTarih 
   begin
       Insert Into @Gunler (Tarih, sGun, sAy, Yil, Ay, Gun, YilHafta, HaftaGun, AyHaftaYontem1, AyHaftaYontem2, TatilSekli)
       Values (
               @Tarih, DateName(Weekday, @Tarih), DateName(Month, @Tarih), DatePart(Year, @Tarih), DatePart(Month, @Tarih), DatePart(Day, @Tarih), DatePart(Week, @Tarih), DatePart(Weekday, @Tarih),
               (DatePart(Week, @Tarih) - DatePart(Week, DateAdd(MM, DateDiff(MM, 0, @Tarih), 0)) + 1),
               0,
               Case 
                   When ( DatePart(Month, @Tarih) = 1 And DatePart(day, @Tarih) = 1 ) Then 1 /* Yıl Başı*/
                   When ( DatePart(Month, @Tarih) = 7 And DatePart(day, @Tarih) = 15 ) Then 2 /* 15 Temmuz */
                   When ( DatePart(Month, @Tarih) = 10 And DatePart(day, @Tarih) = 28 ) Then 2 /* 29 Ekim Yarım*/
                   When ( DatePart(Month, @Tarih) = 10 And DatePart(day, @Tarih) = 29 ) Then 1 /* 29 Ekim Tam*/
               Else
                   0
               end
              )

       Set @Tarih = DateAdd(Day, 1, @Tarih)
   End
   
   Update @Gunler
   Set AyHaftaYontem2 = T.Yontem2
   From @Gunler G
       Inner Join (Select Tarih, (Dense_Rank() Over (Partition By Month(Tarih) Order By DatePart(Week, Tarih) Asc)) As Yontem2
                   From @Gunler
                  ) T On T.Tarih = G.Tarih
   
   Select * 
   From @Gunler
   Order By Tarih
Bende şu şekilde bir çözüm buldum.

Kod:
Set DateFormat dmy
   Declare @Gunler Table (Tarih DateTime)
   Declare @Tarih DateTime
   Declare @BasTarih DateTime
   Declare @BitTarih DateTime

   Set @BasTarih = Cast('20230101' As DateTime)
   Set @BitTarih = Cast('20230331' As DateTime)

   Set @Tarih = @BasTarih
   While @Tarih <= @BitTarih
   begin
       Insert Into @Gunler (Tarih)
       Values (@Tarih)
       Set @Tarih = DateAdd(Day, 1, @Tarih)
   End

   Set DateFirst 1
   Select T.*,
        case when ilkpazar >= Tarih then 1 else  (DATEDIFF(DAY,ilkpazar+1,Tarih) ) / 7 +2 END AS X
   From (
           Select G.Tarih,
               DateName(Weekday, G.Tarih) As Gün,  
               DatePart(Year, G.Tarih) As Yil,
               DatePart(Month, G.Tarih) As Ay,
               DatePart(Week, G.Tarih) As YilHafta,
               DatePart(Weekday,G.Tarih) As HaftaGun,
                DATEADD(mm, DATEDIFF(mm, 0,G.Tarih), 0) + (7- (DatePart(Weekday,DATEADD(mm, DATEDIFF(mm, 0,G.Tarih), 0))) ) AS ilkpazar

           From @Gunler G
       ) T
   Order By T.Tarih --T.Yil, T.HaftaGun, T.Ay
Şu şekilde tek bir SELECT ifadesi ile çözümü vardır.
Sql 2022 versiyonunda desteklenen fonksiyonlar mecuttur

SET DATEFIRST 1 ;

DECLARE @baslangic DATETIME = '2023-01-01';
DECLARE @bitis DATETIME = '2023-03-30';


SELECT c2.Tarih1 AS HaftaBasi,
       c2.Tarih2 AS HaftaSonu,
       DATENAME(MONTH,C2.Tarih1) AS Ay,
       CONCAT(ROW_NUMBER() OVER win,'.HAFTA') AS Hafta
FROM (SELECT GREATEST(@baslangic, DATEFROMPARTS(VALUE/100, VALUE % 100,1)) AS Baslama,
             LEAST(@bitis,EOMONTH(DATEFROMPARTS(VALUE/100, VALUE % 100,1))) AS Bitis
      FROM GENERATE_SERIES(YEAR(@baslangic)*100+MONTH(@baslangic), YEAR(@bitis)*100+MONTH(@bitis))
    ) AS G
CROSS APPLY (SELECT c.Tarih1,
                    LEAD(c.Tarih1-1,1,EOMONTH(c.Tarih1)) OVER win AS Tarih2
             FROM GENERATE_SERIES(DAY(g.Baslama), DAY(g.Bitis)) as t
             CROSS APPLY (SELECT t.Tarih1 FROM (VALUES(DATEADD(DAY,VALUE-1,g.Baslama))) AS t(Tarih1)) AS c
             WHERE DATEPART(dw,c.Tarih1) = 1 OR 
                   (DATEPART(dw,c.Tarih1) > 1 AND c.Tarih1=g.Baslama)
             WINDOW win AS (ORDER BY c.Tarih1)
            ) AS c2
WINDOW win AS (PARTITION BY YEAR(c2.Tarih1),YEAR(c2.Tarih2),MONTH(c2.Tarih1),MONTH(c2.Tarih2) ORDER BY C2.Tarih1)
ORDER BY C2.Tarih1