SUPERCAT.DEV

Benvenut* sul mio blog

TSQL

Creazione calendario in SQL

23-09-2024

Con prefestivi e festivi

Primo creo una funzione che calcola il giorno della Pasqua

CREATE FUNCTION [DBO].[CALCOLAGIORNOPASQUA](@ANNO AS SMALLINT)
RETURNS DATETIME AS  
BEGIN 

DECLARE @MESE AS VARCHAR(2)
DECLARE @GIORNO AS VARCHAR(2)
DECLARE @ANNOS AS VARCHAR(4)
DECLARE @A AS SMALLINT, @B AS SMALLINT, @C AS SMALLINT, @D AS SMALLINT, @E AS SMALLINT,	@M AS SMALLINT, @N AS SMALLINT
DECLARE @DA AS SMALLINT, @MO AS SMALLINT

SET @M = 24
SET @N = 5

SET @A = @ANNO % 19
SET @B = @ANNO % 4
SET @C = @ANNO % 7
SET @D = ((19 * @A) + @M) % 30
SET @E = ((2 * @B) + (4 * @C) + (6 * @D) + @N) % 7

IF (@D + @E < 10) 
BEGIN
    SET @DA = @D + @E + 22
    SET @MO = 3
END
ELSE
BEGIN
    SET @DA = @D + @E - 9
    SET @MO = 4
END

IF (@DA = 26 AND @MO = 4) 
BEGIN
    SET @DA = 19
    SET @MO = 4
END
ELSE
BEGIN
    IF (@DA = 25 AND @MO = 4 AND @D = 28 AND @E = 6 AND @A > 10) 
    BEGIN
        SET @DA = 18
        SET @MO = 4
    END 
END

SET @ANNOS = LTRIM(RTRIM(STR(@ANNO)))
SET @MESE = RIGHT('00' +  LTRIM(RTRIM(STR(@MO))),2)
SET @GIORNO = RIGHT('00' +  LTRIM(RTRIM(STR(@DA))),2)

RETURN CONVERT(DATETIME,@ANNOS+@MESE+@GIORNO)

END

Estraggo la tabella con indicati festivi e prefestivi

-- VARIABILI
DECLARE @ANNO INT = 2025
DECLARE @PREFESTIVO VARCHAR(20) = 'Prefestivo'
DECLARE @FESTIVO VARCHAR(20) = 'Festivo'
DECLARE @NORMALE VARCHAR(20) = 'Normale'
SET DATEFIRST 1
-- FINE VARIABILI

DECLARE @DATA_INIZIO DATE
DECLARE @DATA_FINE DATE

DECLARE @CALENDARIO TABLE (
      ROWID INT NOT NULL PRIMARY KEY IDENTITY(1,1)
    , [DATA] DATE
    , GIORNO_SETTIMANA VARCHAR(20)
    , TIPO VARCHAR(20)
    , N_SETTIMANA INT
    , GIORNO INT
    , MESE INT
    , ANNO INT
    , PROCESSATO INT DEFAULT 0
    )

SELECT
   @DATA_INIZIO = CONVERT(VARCHAR(4), @ANNO) + '-01-01',
   @DATA_FINE = CONVERT(VARCHAR(4), @ANNO) + '-12-31'

DECLARE @DATE INT
WITH CTE_CALENDARIO
AS
(
  SELECT CAST(@DATA_INIZIO AS DATE) AS [DATE]
  UNION ALL
  SELECT DATEADD(DD, 1, [DATE])
  FROM CTE_CALENDARIO
  WHERE DATEADD(DD, 1, [DATE]) <= @DATA_FINE
)
INSERT INTO @CALENDARIO ([DATA], GIORNO_SETTIMANA, TIPO, N_SETTIMANA, GIORNO, MESE, ANNO)
SELECT 
     [DATE]
    ,(
        SELECT CASE DATEPART(WEEKDAY,[DATE])  
            WHEN 1 THEN 'Lunedì' 
            WHEN 2 THEN 'Martedì' 
            WHEN 3 THEN 'Mercoledì' 
            WHEN 4 THEN 'Giovedì' 
            WHEN 5 THEN 'Venerdì' 
            WHEN 6 THEN 'Sabato' 
            WHEN 7 THEN 'Domenica' 
        END 
    )
    , @NORMALE
    ,DATEPART(WEEK, [DATE])
    ,DATEPART(DAY,[DATE])
    ,DATEPART(MONTH, [DATE])
    ,DATEPART(YEAR,[DATE])
FROM CTE_CALENDARIO
OPTION (MAXRECURSION 0);

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE GIORNO_SETTIMANA = 'Domenica' 

UPDATE @CALENDARIO
    SET TIPO = @PREFESTIVO
WHERE GIORNO_SETTIMANA = 'Sabato'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-01-01'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-01-06'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-04-25'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = DATEADD(DAY, 1, dbo.CALCOLAGIORNOPASQUA(@ANNO)) -- PASQUETTA

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-05-01'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-06-02'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-08-15'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-11-01'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-12-08'

UPDATE @CALENDARIO
    SET TIPO = @PREFESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-12-24' 

UPDATE @CALENDARIO
    SET TIPO = @PREFESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-12-25'

UPDATE @CALENDARIO
    SET TIPO = @FESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-12-26'

UPDATE @CALENDARIO
    SET TIPO = @PREFESTIVO
WHERE [DATA] = CONVERT(VARCHAR(4), @ANNO) + '-12-31'

DECLARE @ROWID INT
WHILE (SELECT COUNT(*) FROM @CALENDARIO WHERE PROCESSATO = 0) > 0
BEGIN
    DECLARE @TIPO_OGGI VARCHAR(20) = ''
    DECLARE @TIPO_PREC VARCHAR(20) = ''
    DECLARE @TIPO_SUCC VARCHAR(20) = ''

    DECLARE @GIORNO_OGGI VARCHAR(20) = ''
    DECLARE @GIORNO_PREC VARCHAR(20) = ''
    DECLARE @GIORNO_SUCC VARCHAR(20) = ''

    SELECT TOP 1 @ROWID = ROWID, @TIPO_OGGI = TIPO, @GIORNO_OGGI = GIORNO_SETTIMANA FROM @CALENDARIO WHERE PROCESSATO = 0

    IF @ROWID > 1
    BEGIN
        SELECT TOP 1 @TIPO_PREC = TIPO, @GIORNO_PREC = GIORNO_SETTIMANA  FROM @CALENDARIO WHERE ROWID = @ROWID - 1

        IF @TIPO_OGGI = @FESTIVO AND @TIPO_PREC <> @PREFESTIVO
        BEGIN
            UPDATE @CALENDARIO SET TIPO = @PREFESTIVO WHERE ROWID = @ROWID - 1
        END        
    END

    IF (@ROWID + 1) < (SELECT MAX(ROWID) FROM @CALENDARIO)
    BEGIN
        SELECT TOP 1 @TIPO_SUCC = TIPO, @GIORNO_SUCC = GIORNO_SETTIMANA FROM @CALENDARIO WHERE ROWID = @ROWID + 1

        IF @TIPO_OGGI = @FESTIVO AND @TIPO_SUCC = @FESTIVO
        BEGIN
            UPDATE @CALENDARIO SET TIPO = @PREFESTIVO WHERE ROWID = @ROWID
        END
    END
    
    UPDATE @CALENDARIO SET PROCESSATO = 1 WHERE ROWID = @ROWID		
END;

SELECT * FROM @CALENDARIO