получить DATEDIFF за исключением выходных с использованием сервера sql - PullRequest
25 голосов
/ 12 сентября 2011

Я использую этот запрос, чтобы получить время.

SELECT DATEDIFF(dd, ActualStartDate, ActualCompletionDate) AS TimeTaken
FROM TableName

Теперь я хочу исключить выходные и включать только пн-пт в качестве числа дней.

Ответы [ 8 ]

51 голосов
/ 12 сентября 2011

Пример запроса ниже, вот некоторые подробности того, как я его решил.

Использование DATEDIFF(WK, ...) даст нам количество недель между двумя датами. SQL Server оценивает это как разницу между номерами недель, а не на основе количества дней. Это прекрасно, так как мы можем использовать это, чтобы определить, сколько выходных прошло между датами.

Таким образом, мы можем умножить это значение на 2, чтобы получить количество дней выходных, которые произошли, и вычесть это значение из DATEDIFF(dd, ...), чтобы получить количество дней недели.

Это не ведет себя на 100% правильно, когда дата начала или окончания приходится на воскресенье. Поэтому я добавил в некоторых случаях логику в конце вычисления для обработки этих экземпляров.

Вы также можете подумать, должен ли DATEDIFF быть полностью включенным. например Разница между 9/10 и 9/11 1 день или 2 дня? Если последнее, вам нужно добавить 1 к конечному продукту.

declare @d1 datetime, @d2 datetime
select @d1 = '9/9/2011',  @d2 = '9/18/2011'

select datediff(dd, @d1, @d2) - (datediff(wk, @d1, @d2) * 2) -
       case when datepart(dw, @d1) = 1 then 1 else 0 end +
      case when datepart(dw, @d2) = 1 then 1 else 0 end
5 голосов
/ 29 января 2013

Я обнаружил, когда я использовал это, была проблема, когда d1 упал в субботу.Вот то, что я использовал, чтобы исправить это.

1 голос
/ 19 октября 2018

Если вы ненавидите операторы CASE так же сильно, как и я, и хотите иметь возможность использовать встроенное решение в своих запросах, просто получите разницу дней и вычтите количество выходных дней, и вы получите желаемый результат:

declare @d1 datetime, @d2 datetime,  @days int
select @d1 = '2018/10/01',  @d2 = '2018/11/01'

SET @days = DateDiff(dd, @d1, @d2) - DateDiff(ww, @d1, @d2)*2
print @days

(Единственное предостережение - или, по крайней мере, пункт, о котором следует помнить, - это то, что этот расчет не включает последнюю дату, поэтому вам может потребоваться добавить один день к дате окончания, чтобы достичь результат)

1 голос
/ 13 мая 2016
BEGIN 
DECLARE @totaldays INT; 
DECLARE @weekenddays INT;

SET @totaldays = DATEDIFF(DAY, @startDate, @endDate) 
SET @weekenddays = ((DATEDIFF(WEEK, @startDate, @endDate) * 2) + -- get the number of weekend days in between
                       CASE WHEN DATEPART(WEEKDAY, @startDate) = 1 THEN 1 ELSE 0 END + -- if selection was Sunday, won't add to weekends
                       CASE WHEN DATEPART(WEEKDAY, @endDate) = 6 THEN 1 ELSE 0 END)  -- if selection was Saturday, won't add to weekends

Return (@totaldays - @weekenddays)

END

Это на SQL Server 2014

0 голосов
/ 12 февраля 2019

/ * ПРИМЕР: / понедельник / SET DATEFIRST 1 ВЫБЕРИТЕ dbo.FUNC_GETDATEDIFFERENCE_WO_WEEKEND ('2019-02-01', '2019-02-12') * / CREATE FUNCTION FUNC_GETDATEDIFFERENCE_WO_WEEKEND ( @pdtmaLastLoanPayDate DATETIME, @pdtmaDisbursedDate DATETIME ) ВОЗВРАЩАЕТСЯ BIGINT НАЧАТЬ

DECLARE
@mintDaysDifference     BIGINT

SET @mintDaysDifference = 0

WHILE CONVERT(NCHAR(10),@pdtmaLastLoanPayDate,121) <= CONVERT(NCHAR(10),@pdtmaDisbursedDate,121)
BEGIN
    IF DATEPART(WEEKDAY,@pdtmaLastLoanPayDate) NOT IN (6,7)
    BEGIN
        SET @mintDaysDifference = @mintDaysDifference + 1
    END

    SET @pdtmaLastLoanPayDate = DATEADD(DAY,1,@pdtmaLastLoanPayDate)
END

RETURN ISNULL(@mintDaysDifference,0)

END

0 голосов
/ 30 ноября 2017

Используя https://stackoverflow.com/a/1804095 и ответ JeffFisher30 выше (https://stackoverflow.com/a/14572370/6147425) и мою собственную потребность в дробных днях, я написал это:

DateDiff(second,Start_Time,End_Time)/86400.0
            -2*DateDiff(week, Start_Time, End_Time)
            -Case When (DatePart(weekday, Start_Time)+@@DateFirst)%7 = 1 Then 1 Else 0 End
            +Case When (DatePart(weekday, End_Time)+@@DateFirst)%7 = 1 Then 1 Else 0 End
0 голосов
/ 14 июня 2017

Я просто хочу поделиться созданным мною кодом, который может вам помочь.

DECLARE @MyCounter int = 0, @TempDate datetime, @EndDate datetime;
SET @TempDate = DATEADD(d,1,'2017-5-27')
SET @EndDate = '2017-6-3'

WHILE @TempDate <= @EndDate
    BEGIN
    IF DATENAME(DW,@TempDate) = 'Sunday' OR DATENAME(DW,@TempDate) = 'Saturday'
        SET @MyCounter = @MyCounter
    ELSE IF @TempDate not in ('2017-1-1', '2017-1-16', '2017-2-20', '2017-5-29', '2017-7-4', '2017-9-4', '2017-10-9', '2017-11-11', '2017-12-25')
        SET @MyCounter = @MyCounter + 1

    SET @TempDate = DATEADD(d,1,@TempDate)
    CONTINUE

END
PRINT @MyCounter
PRINT @TempDate

Если у вас есть таблица праздничных дней, вы также можете использовать ее, чтобы вам не приходилось указывать все праздничные дни в разделе кода ELSE IF. Вы также можете создать функцию для этого кода и использовать ее всякий раз, когда она понадобится в вашем запросе.

Надеюсь, это тоже поможет.

0 голосов
/ 19 апреля 2017
declare @d1 datetime, @d2 datetime
select @d1 = '4/19/2017',  @d2 = '5/7/2017'

DECLARE @Counter int = datediff(DAY,@d1 ,@d2 )

DECLARE @C int = 0
DECLARE @SUM int = 0





 WHILE  @Counter > 0
  begin
 SET @SUM = @SUM + IIF(DATENAME(dw, 

 DATEADD(day,@c,@d1))IN('Sunday','Monday','Tuesday','Wednesday','Thursday')
 ,1,0)



SET @Counter = @Counter - 1
set @c = @c +1
end

select @Sum
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...