Funzione per restituire un giorno specifico del mese
Questo è stato utile per il nostro piano di manutenzione, poiché possiamo utilizzare uno script e aggiungere codice che verrà eseguito in un giorno specifico (come l'ultima domenica o il 1° giorno della settimana), l'ho anche usato per prevedere i tempi in cui i lavori verranno eseguiti i nostri server.
La funzione richiede solo tre input, il mese che ti interessa, il tipo e il numero.
Utilizza informazioni simili a quelle utilizzate da Microsoft per le pianificazioni dei lavori mensili.
SQL
CREATE FUNCTION dbo.GetMonthDay(@Month DATETIME,@Type INT, @Counter INT) RETURNS DATETIME AS BEGINSET @Month = CONVERT(DATE,DATEADD(DAY,1-DATEPART(DAY,@Month),@Month))DECLARE @CurDate DATETIME=@Month,@Date DATETIME,@Matches INT=0,@TempDate DATETIMEWHILE @CurDate IF (SELECT (CASE @Type WHEN 1 THEN (CASE WHEN DATEPART(WeekDay,@CurDate)=1 THEN 1 ELSE 0 END)WHEN 2 THEN(CASE WHEN DATEPART(WeekDay,@CurDate)=2 THEN 1 ELSE 0 END)WHEN 3 THEN(CASE WHEN DATEPART(WeekDay,@CurDate)=3 THEN 1 ELSE 0 END)WHEN 4 THEN(CASE WHEN DATEPART(WeekDay,@CurDate)=4 THEN 1 ELSE 0 END)WHEN 5 THEN(CASE WHEN DATEPART(WeekDay,@CurDate)=5 THEN 1 ELSE 0 END)WHEN 6 THEN(CASE WHEN DATEPART(WeekDay,@CurDate)=6 THEN 1 ELSE 0 END)WHEN 7 THEN(CASE WHEN DATEPART(WeekDay,@CurDate)=7 THEN 1 ELSE 0 END)WHEN 8 THEN(CASE WHEN DATEPART(WeekDay,@CurDate) IN (1,2,3,4,5,6,7) THEN 1 ELSE 0 END)WHEN 9 THEN(CASE WHEN DATEPART(WeekDay,@CurDate) IN (2,3,4,5,6) THEN 1 ELSE 0 END)WHEN 10 THEN (CASE WHEN DATEPART(WeekDay,@CurDate) IN (1,7) THEN 1 ELSE 0 END)ELSE 0 END))=1 BEGINSET @Matches = @Matches+1SET @TempDate = @CurDateENDIF @Matches=@Counter AND @Counter<32 BEGINSET @Date=@TempDateENDSET @CurDate=DATEADD(DAY,1,@CurDate)ENDRETURN ISNULL(@Date,@TempDate)ENDGO
Cosa fa
I valori che abbiamo sono simili alla tabella sysschedules ma li elencherò qui;
@Tipo
- 1=domenica
- 2=lunedì
- 3=Martedì
- 4=Mercoledì
- 5=giovedì
- 6=venerdì
- 7=Sabato
- 8=qualsiasi giorno fino al contatore o ultimo giorno del mese
- 9=qualsiasi giorno della settimana fino allo sportello o l'ultimo giorno del mese
- 10=ogni sabato o domenica fino allo sportello o l'ultima occorrenza del mese
@Contatore
- 1=1°
- 2=2°
- 3=3°
- 4=4°
- 32=Ultimo (questi sono leggermente diversi)
I passaggi che segue sono i seguenti;
- Impostare la data di immissione sul primo giorno del mese
- Dichiara le variabili per il nostro ciclo del mese
- Scorri ogni data e aggiorna il conteggio delle partite se c'è una corrispondenza e aggiorna una data temporanea per tenere l'ultima partita
- Se le corrispondenze sono uguali al nostro contatore e il contatore è inferiore a 5 (5 = ultimo giorno), imposta la nostra data di ritorno come data temporanea, questo uscirà dal ciclo poiché la data non è più nulla.
- Aggiungine uno alla nostra data corrente ed esegui nuovamente il nostro controllo.
- Restituisce la nostra data o, se nulla, la data temporanea che è stata la nostra ultima corrispondenza.
Di seguito è riportato un esempio in uso. Questo si svolgerà ogni domenica di febbraio.
È possibile utilizzarlo in una clausola IF per determinare se eseguire o meno determinate parti di una stored procedure.
Testing
SELECT Utilities.dbo.GetMonthDay('2020-02-11',1,1) --2020-02-02 00:00:00.000SELECT Utilities.dbo.GetMonthDay('2020-02-11',1,2) --2020-02-09 00:00:00.000SELECT Utilities.dbo.GetMonthDay('2020-02-11',1,3) --2020-02-16 00:00:00.000SELECT Utilities.dbo.GetMonthDay('2020-02-11',1,4) --2020-02-23 00:00:00.000SELECT Utilities.dbo.GetMonthDay('2020-02-11',1,32)--2020-02-23 00:00:00.000IF Utilities.dbo.GetMonthDay('2020-02-11',1,32)='2020-02-23' BEGINSELECT 'Run your code'END
Ulteriori letture
Spero che questo possa esserti utile o ti dia un'idea per altri processi.
Se devi calcolare con le festività, avrai bisogno di una tabella del calendario e puoi vedere un ottimo esempio sul link qui sotto.