两个日期之间的DATEDIFF,不包括特定日期

时间:2018-11-29 15:02:36

标签: sql-server

SQL服务器 创建函数来计算参数的2个日期之间的差值是我要从持续时间中排除的天数???

  

Blockquote

示例:从4-11-2018到29-11-2018,如果我通过星期日和星期一,则结果必须排除每个星期日和星期一,持续时间为   26(总天数)-8(排除天数)= 18天

2 个答案:

答案 0 :(得分:0)

请给出以下解决方案,不确定是否是最好的解决方案,但强烈怀疑仍然存在简单的解决方案。

@from和@to日期包括在计算中。

如果需要更多信息,请留下评论。

在SqlServer上测试。

-- declare params
declare @from datetime = '2018-09-29 00:00:00.000'
declare @to datetime = getdate()

declare @param nvarchar(150) = 'Monday Wednesday'
declare @daysToSunstract int = 0

-- find days to substract based on @param
if (@param like '%Monday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -7, @to)/7-datediff(day, -6, @from)/7)
if (@param like '%Tuesday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -6, @to)/7-datediff(day, -5, @from)/7)
if (@param like '%Wednesday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -5, @to)/7-datediff(day, -4, @from)/7)
if (@param like '%Thursday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -4, @to)/7-datediff(day, -3, @from)/7)
if (@param like '%Friday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -3, @to)/7-datediff(day, -2, @from)/7)
if (@param like '%Saturday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -2, @to)/7-datediff(day, -1, @from)/7)
if (@param like '%Sunday%')
    set @daysToSunstract = @daysToSunstract + (select datediff(day, -1, @to)/7-datediff(day, 0, @from)/7)

-- final result
select datediff(day, @from, @to)+1 - @daysToSunstract as TotalDays

现在,您需要在存储过程中包含以上逻辑。

  

FUNCTION选项

CREATE FUNCTION [dbo].[DAYS_BETWEEN_DATES] (@from datetime, @to datetime, @exclude NVARCHAR(150))
RETURNS INT
AS
BEGIN
    declare @daysToSunstract int = 0

    -- find days to substract based on @param
    if (@exclude like '%Monday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -7, @to)/7-datediff(day, -6, @from)/7)
    if (@exclude like '%Tuesday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -6, @to)/7-datediff(day, -5, @from)/7)
    if (@exclude like '%Wednesday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -5, @to)/7-datediff(day, -4, @from)/7)
    if (@exclude like '%Thursday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -4, @to)/7-datediff(day, -3, @from)/7)
    if (@exclude like '%Friday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -3, @to)/7-datediff(day, -2, @from)/7)
    if (@exclude like '%Saturday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -2, @to)/7-datediff(day, -1, @from)/7)
    if (@exclude like '%Sunday%')
        set @daysToSunstract = @daysToSunstract + (select datediff(day, -1, @to)/7-datediff(day, 0, @from)/7)

    -- final result
    return (select datediff(day, @from, @to)+1 - @daysToSunstract as TotalDays)
END

测试:

select [dbo].[DAYS_BETWEEN_DATES]('2018-09-29', '2018-11-29', 'Monday,Friday')

答案 1 :(得分:0)

要根据变量进行计算,可以使用递归CTE来获取该范围内的日期及其对应的工作日。
然后计算那些工作日。

DECLARE @StartDate DATE = '2018-11-04';
DECLARE @StopDate DATE = '2018-11-29';
DECLARE @WorkDays INT;

SET DATEFIRST 1; -- Monday as first weekday
DECLARE @WeekendDay1 INT = 7; -- 7: Sunday, when @@DATEFIRST = 1
DECLARE @WeekendDay2 INT = 1; -- 1: Monday, when @@DATEFIRST = 1

WITH DATES AS 
(
    SELECT @StartDate dt, DATEPART(weekday, @StartDate) wd
    UNION ALL
    SELECT DATEADD(DAY,1,dt), DATEPART(weekday, DATEADD(DAY,1,dt)) wd
    FROM DATES
    WHERE dt < @StopDate   
)
SELECT @WorkDays = COUNT(*)
FROM DATES
WHERE wd NOT IN (@WeekendDay1, @WeekendDay2) 
OPTION(MAXRECURSION 366);

SELECT @WorkDays AS WorkDays;

但是,如果您有一个包含所有日期的永久表,则可以使用该表。

SET DATEFIRST 1;

SELECT COUNT(*)
FROM Calendar
WHERE [Date] BETWEEN @StartDate AND @StopDate
  AND DATEPART(weekday, [Date]) NOT IN (@WeekendDay1, @WeekendDay2);

如果该表包含假期,那么您也可以在条件中使用它。