/*********************************************************************************** * FUNCTION f_diffOreLavorative * * calcola le effettive ore lavorative sottraendo chiusure x festività o aperture programmate * ***********************************************************************************/ create FUNCTION f_diffOreLavorative ( @dataFrom DATETIME, @dataTo DATETIME, @idxMacchina INT -- per ora non lo considero poiché non ci sono calendari diversi x macchina... ) RETURNS FLOAT AS BEGIN -- dichiarazioni variabili DECLARE @oreTot AS FLOAT DECLARE @oreOff AS FLOAT DECLARE @tmp_dates TABLE (DateValue DATETIME, h INT) SET @oreTot = 0 -- controllo date coerenti IF(@dataTo > @dataFrom) BEGIN -- calcolo totale "raw" delle ore SET @oreTot = CAST(ISNULL(DATEDIFF(minute, @dataFrom, @dataTo), 0) AS float) / 60; -- definisco tabella cte ricorsiva WITH mycte AS ( SELECT CAST(dbo.f_dateOnly(DATEADD(dd,1,@dataFROM)) AS DATETIME) DateValue UNION ALL SELECT DateValue + 1 FROM mycte WHERE DateValue + 1 < dbo.f_dateOnly(@dataTo) ) -- carico nella tab temporanea i sabati e le domeniche... INSERT into @tmp_dates(DateValue, h) SELECT *, CASE ((DATEPART(dw, DateValue) + @@DATEFIRST) % 7) WHEN 0 THEN 16 ELSE 24 END AS h FROM mycte WHERE ((DATEPART(dw, DateValue) + @@DATEFIRST) % 7) IN (0,1) OPTION (MAXRECURSION 0) -- carico le festività per le date NON ancora presenti insert into @tmp_dates(DateValue, h) select data as DateValue, 24 as h--, descrizione from CalendFesteFerie where data between @dataFrom and @dataTo and data not in (select distinct DateValue from @tmp_dates) -- aggiorno sabati/domenica che fossero festivi (ipotesi che hfest > h sab/dom... UPDATE @tmp_dates SET h=24 WHERE DateValue in (SELECT data FROM CalendFesteFerie WHERE data between @dataFrom and @dataTo) -- calcolo INFINE le ore off! SET @oreOff = (SELECT ISNULL(SUM(h),0) FROM @tmp_dates) END -- setto le nuove ore totali... se ho un numero di ore > delle fermate le sottraggo per evitare ore engative... IF(@oreTot > @oreOff) BEGIN SET @oreTot = @oreTot - @oreOff END RETURN @oreTot END