복붙노트

[SQL] SQL 서버에서 (월요일 ~ 금요일)을 제외한 주말에 일을 계산

SQL

SQL 서버에서 (월요일 ~ 금요일)을 제외한 주말에 일을 계산

어떻게 테이블에서 2008 SQL Server의 (마지막에 1 행에서) 두 날짜 사이에 작업 일 수를 계산할 수있다?

나는 이런 식으로 뭔가를 시도하지만, 일을하지 않습니다

DECLARE @StartDate as DATETIME, @EndDate as DATETIME

Select @StartDate = date2 from testtable ;
select @EndDate = date1 from testtable ;

SELECT
   (DATEDIFF(dd, @StartDate, @EndDate) + 1)
  -(DATEDIFF(wk, @StartDate, @EndDate) * 2)
  -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END)
  -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)

해결법

  1. ==============================

    1.난 항상 일정 테이블을 추천 할 것입니다, 당신은 간단하게 사용할 수 있습니다 :

    난 항상 일정 테이블을 추천 할 것입니다, 당신은 간단하게 사용할 수 있습니다 :

    SELECT  COUNT(*)
    FROM    dbo.CalendarTable
    WHERE   IsWorkingDay = 1
    AND     [Date] > @StartDate
    AND     [Date] <= @EndDate;
    

    SQL 예를 들어 공휴일에 대한 지식이 없기 때문에 두 날짜 사이의 평일의 수는 항상 작업 일 수를 나타내지 않습니다. 달력 테이블이 대부분의 데이터베이스를위한 필요한 이유입니다. 그들은 많은 메모리를 가지고 쿼리를 많이 간단하지 않습니다.

    이 옵션을 선택하지 않습니다하지만 당신은 즉석에서 비교적 쉽게 날짜의 테이블을 생성하고 이것을 사용할 수 있습니다

    SET DATEFIRST 1;
    DECLARE @StartDate DATETIME = '20131103', 
            @EndDate DATETIME = '20131104';
    
    -- GENERATE A LIST OF ALL DATES BETWEEN THE START DATE AND THE END DATE
    WITH AllDates AS
    (   SELECT  TOP (DATEDIFF(DAY, @StartDate, @EndDate))
                D = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.Object_ID), @StartDate)
        FROM    sys.all_objects a
                CROSS JOIN sys.all_objects b
    )
    SELECT  WeekDays = COUNT(*)
    FROM    AllDates
    WHERE   DATEPART(WEEKDAY, D) NOT IN (6, 7);
    

    편집하다

    두 날짜 열 사이의 차이를 계산해야하는 경우 당신은 여전히 ​​귀하의 일정 테이블을 사용할 수 있습니다 :

    SELECT  t.ID,
            t.Date1,
            t.Date2,
            WorkingDays = COUNT(c.DateKey)
    FROM    TestTable t
            LEFT JOIN dbo.Calendar c
                ON c.DateKey >= t.Date1
                AND c.DateKey < t.Date2
                AND c.IsWorkingDay = 1
    GROUP BY t.ID, t.Date1, t.Date2;
    

    SQL-바이올린에 예

  2. ==============================

    2.이것은이 일이 밖으로 제외하지만 않는 날짜 부분보다는 설명입니다. 당신은 당신의 쿼리의 값에 대한 예제로 사용 된 매개 변수를 대체 할 수 있습니다.

    이것은이 일이 밖으로 제외하지만 않는 날짜 부분보다는 설명입니다. 당신은 당신의 쿼리의 값에 대한 예제로 사용 된 매개 변수를 대체 할 수 있습니다.

    Declare 
        @startdate datetime = '2013-11-01', 
        @enddate datetime = '2013-11-11'
    
    
    SELECT
       (DATEDIFF(dd, @StartDate, @EndDate) + 1)
      -(DATEDIFF(wk, @StartDate, @EndDate) * 2)
      -(case datepart(dw, @StartDate)+@@datefirst when 8 then 1 else 0 end) 
      -(case datepart(dw, @EndDate)+@@datefirst when 7 then 1 when 14 then 1 else 0 end) 
    
    Returns 7
    
  3. ==============================

    3.GarethD의 대답에 추가하려면 - 나는 SQL을 원하는 사람을 위해 ... is_working_day = false로 설정된 모든 공휴일과 주말로 일정 테이블의 미국 버전을 함께 SQL을 넣고, 여기있다 :

    GarethD의 대답에 추가하려면 - 나는 SQL을 원하는 사람을 위해 ... is_working_day = false로 설정된 모든 공휴일과 주말로 일정 테이블의 미국 버전을 함께 SQL을 넣고, 여기있다 :

    declare @start_dt as date = '1/1/2009';     -- Date from which the calendar table will be created.
    declare @end_dt as date = '1/1/2030';       -- Calendar table will be created up to this date (not including).
    
    create table CalendarTable (
     date_id date primary key,
     date_year smallint,
     date_month tinyint,
     date_day tinyint,
     weekday_id tinyint,
     weekday_nm varchar(10),
     month_nm varchar(10),
     day_of_year smallint,
     quarter_id tinyint,
     first_day_of_month date,
     last_day_of_month date,
     start_dts datetime,
     end_dts datetime,
     week_number_of_month int,
     is_working_day bit,
    )
    
    while @start_dt < @end_dt
    begin
        insert into CalendarTable(
            date_id, date_year, date_month, date_day, 
            weekday_id, weekday_nm, month_nm, day_of_year, quarter_id, 
            first_day_of_month, last_day_of_month, 
            start_dts, end_dts, week_number_of_month, is_working_day
        )   
        values(
            @start_dt, year(@start_dt), month(@start_dt), day(@start_dt), 
            datepart(weekday, @start_dt), datename(weekday, @start_dt),     datename(month, @start_dt), datepart(dayofyear, @start_dt), datepart(quarter,     @start_dt),
            dateadd(day,-(day(@start_dt)-1),@start_dt), dateadd(day,-(day(dateadd(month,1,@start_dt))),dateadd(month,1,@start_dt)), 
            cast(@start_dt as datetime), dateadd(second,-1,cast(dateadd(day, 1, @start_dt) as datetime)), DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH, 0, @start_dt), 0), @start_dt) +1, 0
        )
        set @start_dt = dateadd(day, 1, @start_dt)
    end
    GO
    
    -- Set all non-weekend days as business days
    update CalendarTable set is_working_day = 1 where weekday_id not in (1,7)
    GO
    
    -- New Years Day
    update CalendarTable set is_working_day = 0 where date_month = 1 and date_day = 1
    GO
    
    -- Memorial Day (last Monday of May)
    WITH Memorial_Day AS
    (
        SELECT date_id, date_year, date_day,
        ROW_NUMBER() OVER (PARTITION BY date_year ORDER BY date_day desc) AS RowNumber
        FROM CalendarTable
        where date_month = 5 and weekday_id = 2
    )   
    
    update CalendarTable set is_working_day = 0 where date_id in (SELECT date_id FROM Memorial_Day 
                                                                where rownumber = 1)
    GO
    
    -- Independence Day
    update CalendarTable set is_working_day = 0 where date_month = 7 and date_day = 4
    GO
    
    
    -- Labor Day (first Monday in September)
    WITH Labor_Day AS
    (
        SELECT date_id, date_year, date_day,
        ROW_NUMBER() OVER (PARTITION BY date_year ORDER BY date_day) AS RowNumber
        FROM CalendarTable
        where date_month = 9 and weekday_id = 2
    )   
    
    update CalendarTable set is_working_day = 0 where date_id in (SELECT date_id FROM Labor_Day 
                                                                where rownumber = 1)
    GO
    
    -- Thanksgiving (fourth Thursday in November)
    WITH Thanksgiving AS
    (
        SELECT date_id, date_year, date_day,
        ROW_NUMBER() OVER (PARTITION BY date_year ORDER BY date_day) AS RowNumber
        FROM CalendarTable
        where date_month = 11 and weekday_id = 5
    )   
    
    update CalendarTable set is_working_day = 0 where date_id in (SELECT date_id FROM Thanksgiving 
                                                                where rownumber = 4)
    
    GO
    
    -- Day After Thanksgiving (fourth Friday in November)
    WITH DayAfterThanksgiving AS
    (
        SELECT date_id, date_year, date_day,
        ROW_NUMBER() OVER (PARTITION BY date_year ORDER BY date_day) AS RowNumber
        FROM CalendarTable
        where date_month = 11 and weekday_id = 6
    )   
    
    update CalendarTable set is_working_day = 0 where date_id in (SELECT date_id FROM DayAfterThanksgiving 
                                                                where rownumber = 4)
    
    GO
    
    -- Christmas Day
    update CalendarTable set is_working_day = 0 where date_month = 12 and date_day = 25
    GO
    
  4. ==============================

    4.당신은 단순히 SQL의 DATEDIFF 기능을 사용할 수 있습니다. 그리고 당신은 어떤 경우에 그 날짜 사이 주말을 뺄 수 있습니다. 예를 들어 쿼리 아래에서 확인. 또한 시작 / 종료 날짜 사이에 휴가를 계산할 수 있으며, 최종 선택에서 해당 뺄 수 있습니다.

    당신은 단순히 SQL의 DATEDIFF 기능을 사용할 수 있습니다. 그리고 당신은 어떤 경우에 그 날짜 사이 주말을 뺄 수 있습니다. 예를 들어 쿼리 아래에서 확인. 또한 시작 / 종료 날짜 사이에 휴가를 계산할 수 있으며, 최종 선택에서 해당 뺄 수 있습니다.

    날짜 시간으로 @StartDate 선언 날짜 시간으로 @enddate 선언 설정 @StartDate = GETDATE () - 2; 설정 @enddate = GETDATE () + 3; 선택 @ STARTDATE, @ ENDDATE (DATEDIFF (일, @ STARTDATE, @ ENDDATE + 1) - (2) * DATEDIFF (주 @ STARTDATE, @ ENDDATE))

  5. ==============================

    5.재미있는 질문입니다. 사용 사례를 이해하는 것이 중요하다. 월요일 일요일부터 계산한다면, 우리는 우리가 월요일에 사업의 닫을 때까지 가진 것처럼 어느 날이 말하고 싶은 것입니다. 아니면 월요일이 시작되기 전에 어떤 일이 없다면 어떠한 일이 없습니다 말하고 싶은 것입니다. 우리의 경우 우리는 그들이 평일이라면 좀 발생액을 추정 급여 응용 프로그램에서 작업을했기 때문에 모두 일 (시작과 끝) 계산이 필요했다. 그리고 어떤 일 주말 나중에 휴가 및 초과 근무 기록에 의해 설명 될 것이다.

    재미있는 질문입니다. 사용 사례를 이해하는 것이 중요하다. 월요일 일요일부터 계산한다면, 우리는 우리가 월요일에 사업의 닫을 때까지 가진 것처럼 어느 날이 말하고 싶은 것입니다. 아니면 월요일이 시작되기 전에 어떤 일이 없다면 어떠한 일이 없습니다 말하고 싶은 것입니다. 우리의 경우 우리는 그들이 평일이라면 좀 발생액을 추정 급여 응용 프로그램에서 작업을했기 때문에 모두 일 (시작과 끝) 계산이 필요했다. 그리고 어떤 일 주말 나중에 휴가 및 초과 근무 기록에 의해 설명 될 것이다.

    내 달력을 꺼내 때 나는 토요일이나 일요일 우리에서 계산 그냥 월요일부터 계산을 시작 수있을 때 깨달았다. 그리고 토요일이나 일요일 I를 계산하는 우리는 금요일에 바로 정지 계산을도있어 수있을 때 때. 나는, 시작 및 종료 날짜를 조정 주당 그 5 명 평일 곱한, 7로 나누어 주 수 발견 한 후 나머지를 다시 추가하는 기능을 썼다 그래서. 우리는 주말에 계산을 시작했지만 월요일에 도착하지 않을 때 나는 경우에 대한 계정에 있었나요.

    - ============================================= - 저자 : 토드 P 페인 - 날짜를 만듭니다 2018년 9월 1일를 - 설명 : 두 날짜 사이의 평일의 카운트 번호 - 참조 DateDiff STARTDATE 및 종료 날짜가 포함되어 달리 - 월요일 년 1 월 1 1월 1일 (월요일) FROM은 1을 반환합니다 - ============================================= FUNCTION을 작성 [DBO]. ufnCountWeekdays] ( - 여기에 기능에 대한 매개 변수를 추가 @StartDate 날짜 시간, @EndDate 날짜 시간 ) RETURNS의 INT 같이 BEGIN - 여기 반환 변수를 선언 DECLARE @CountofWeekDays INT = NULL; @TempDate 날짜 시간을 선언;

    -- Could CountBackwords 
    IF @StartDate > @ENDDate
    BEGIN
        SET @TempDate = @StartDate; 
        SET @StartDate = @EndDate;
        SET @EndDate = @TempDate;
    END
    
    --Start on Weekend Never get to Monday Case
    IF (DatePart(dw,@StartDate) = 7 AND DateDiff(Day,@StartDate,@EndDate) < 2)
    OR (DatePart(dw,@StartDate) = 1 AND DateDiff(Day,@StartDate,@EndDate) < 1 )
    BEGIN 
        SET @CountOfWeekDays = 0 -- Never got to a WeekDay
    END
    
    --NORMAL CASE
    ELSE BEGIN 
     -- IF Sat Start just pretend Start Counting on Monday 
     IF (DatePart(dw,@StartDate) = 7) SET @StartDate = dateadd(Day, 2, @StartDate);
     -- IF Sun Start just Start to Counting on Monday 
     IF (DatePart(dw,@StartDate) = 1) SET @StartDate = dateadd(Day, 1, @StartDate);
     -- Sat End just Stop counting on Friday
     IF (DatePart(dw,@EndDate) = 7) SET @EndDate = DateAdd(Day, -1, @EndDate);
     -- Sun END
     if (DatePart(dw,@EndDate) = 1) SET  @EndDate = DateAdd(Day, -2, @EndDate);
     --Find the total number of days we need to count
     Declare @DaysToCount INT = DateDiff(Day,@StartDate, @EndDate)+1; --include start
     -- five days for each full week plus any other weekdays 
     -- remember no worries about starting or ending on weekends
      Set @CountofWeekDays  = Floor(@DaysToCount/7)*5 + (@DaysToCount % 7)
    
    END     
    
    --Check to see if we are counting backwards
    IF @TempDate = @EndDate SET @CountofWeekDays = -1 * @CountofWeekDays;
    
    RETURN @CountofWeekDays;
    

    종료 가다

    해피 코딩

    토드 P 페인

  6. from https://stackoverflow.com/questions/19765962/calculating-days-to-excluding-weekends-monday-to-friday-in-sql-server by cc-by-sa and MIT license