Ab und an geht es mal darum in einer Datenbank den Überlappungs-Zeitraum von 2 Zeiträumen zu ermitteln, oder auch nur ob 2 Zeiträume überhaupt überlappen. Heute stand ich vor dieser Problematik und habe auch keine eingebaute Funktion im MS-SQL-Server gefunden. Die folgenden 2 Funktionen, alle Angaben ohne Gewähr, führen jedenfalls bei mir zum gewünschten Ergebnis:
Überprüfung ob 2 Zeiträume überlappen
ALTER FUNCTION [dbo].[CheckPeriodOverlap] ( -- Add the parameters for the function here @Period1Start date, @Period1End date, @Period2Start date, @Period2End date ) RETURNS bit AS BEGIN DECLARE @IsOverlapping bit = case when @Period1Start <= @Period2Start AND @Period1End >= @Period2End then 1 when @Period1Start <= @Period2Start AND @Period1End >= @Period2Start AND @Period1End <= @Period2End then 1 when @Period1Start >= @Period2Start AND @Period1End <= @Period2End then 1 when @Period1Start <= @Period2End AND @Period1End >= @Period2End then 1 else 0 end -- Return the result of the function RETURN @IsOverlapping END
Ermittlung der Tage, die 2 Zeiträume überlappen
ALTER FUNCTION [dbo].[PeriodOverlappingDays] ( -- Add the parameters for the function here @Period1Start date ,@Period1End date ,@Period2Start date ,@Period2End date ) RETURNS int AS BEGIN declare @OverlappingDays int = 0 declare @p1_1 date = case when @Period1Start < @Period1End then @Period1Start else @Period1End end declare @p1_2 date = case when @Period1Start < @Period1End then @Period1End else @Period1Start end declare @p2_1 date = case when @Period2Start < @Period2End then @Period2Start else @Period2End end declare @p2_2 date = case when @Period2Start < @Period2End then @Period2End else @Period2Start end declare @IsOverlap bit = dbo.CheckPeriodOverlap(@p1_1, @p1_2, @p2_1, @p2_2) if @IsOverlap = 0 begin set @OverlappingDays = 0 end else set @OverlappingDays = case --#1 P1 beginnt vorher und endet in P2 when @p1_1 < @p2_1 and @p1_2 between @p2_1 and @p2_2 then datediff(d, @p2_1, @p1_2) + 1 --#2 P1 beginnt in P2 und endet nach P2 when @p1_1 between @p2_1 and @p2_2 and @p1_2 > @p2_2 then datediff(d, @p1_1, @p2_2) + 1 --#3 P1 beginnt end endet innerhalb P2 when @p1_1 between @p2_1 and @p2_2 and @p1_2 between @p2_1 and @p2_2 then datediff(d, @p1_1, @p1_2) + 1 --#4 P1 beginnt vor und endet nach P2 when @p1_1 < @p2_1 and @p1_2 > @p2_1 then datediff(d, @p2_1, @p2_2) + 1 --#5 P1 und P2 sind identisch when @p1_1 = @p2_1 and @p1_2 = @p2_2 then datediff(d, @p2_1, @p2_2) + 1 --#6 P1 beginnt mit P2 und endet später when @p1_1 = @p2_1 and @p1_2 > @p2_2 then datediff(d, @p2_1, @p2_2) + 1 --#7 P1 beginnt mit P2 und endet früher when @p1_1 = @p2_1 and @p1_2 < @p2_2 then datediff(d, @p1_1, @p1_2) + 1 --#8 P1 beginnt vor P2 und endet mit P2 when @p1_1 < @p2_1 and @p1_2 = @p2_2 then datediff(d, @p2_1, @p2_2) + 1 --#9 P1 beginnt nach P2 und endet mit P2 when @p1_1 > @p2_1 and @p1_2 = @p2_2 then datediff(d, @p1_1, @p1_2) + 1 else null end -- Return the result of the function RETURN @OverlappingDays END