Calculate difference between 2 dates in SQL, excluding weekend days

前端 未结 10 982
礼貌的吻别
礼貌的吻别 2020-12-04 01:34

I would like to build an SQL query which calculates the difference between 2 dates, without counting the week-end days in the result.

Is there any way to format the

相关标签:
10条回答
  • 2020-12-04 02:01

    We've incorporated the following logic into several reports with great success. Sorry, I no longer recall the source of this script to give them credit.

    DECLARE @range INT;
    
    SET @range = DATEDIFF(DAY, @FirstDate, @SecondDate); 
    SET @NumWorkDays = (
        SELECT  
        @range / 7 * 5 + @range % 7 - ( 
            SELECT COUNT(*)  
            FROM ( 
                SELECT 1 AS d 
                UNION ALL SELECT 2  
                UNION ALL SELECT 3  
                UNION ALL SELECT 4  
                UNION ALL SELECT 5  
                UNION ALL SELECT 6  
                UNION ALL SELECT 7 
                ) weekdays 
            WHERE d <= @range % 7  
            AND DATENAME(WEEKDAY, @SecondDate - d) IN ('Saturday', 'Sunday'))
        );
    
    0 讨论(0)
  • 2020-12-04 02:07

    Here is an example:
    There are four variables, the first two are self-explanatory, just enter the date in YYYYMMDD format, the 3rd one is to set the number of normal work days in a given week, so if a site works 6 days a week, set it to 6, five days a week enter 5, etc. Finally, the DATE_SEQ_NORML_FACTOR should be 1 when running against Oracle. This is to line up the Julian date to equal to 1 on Monday, 2 on Tuesday, etc when applying the MOD 7. Other DB will probably have different values between 0 and 6, so test it out before you use against other DBs.

    Here are the limitations: 1. This formula assumes the first day of the week is MONDAY. 2. This formula assumes all days within the same week are CONTINUOUS. 3. This formula will work ONLY when the two dates involved in the calculation falls on a week day or work day, eg. the "Start Date" on a SATURDAY when the location works only MON-FRI will not work.

    SELECT
    
      &&START_DATE_YYYYMMDD "Start Date", --in YYYYMMDD format
    
      &&END_DATE_YYYYMMDD "End Date", --in YYYYMMDD format
    
      &&WK_WORK_DAY_CNT "Week Work Day Count", --Number of work day per week
    
      &&DATE_SEQ_NORML_FACTOR "Normalization Factor", --set to 1 when run in Oracle
    
      CASE
    
      WHEN
    
        FLOOR( TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR / 7 ) =
    
        FLOOR( TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR / 7 )
    
      THEN(
    
        TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) -
    
        TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + 1
    
      )
    
      ELSE(
    
        (
    
          &&WK_WORK_DAY_CNT - MOD( TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 ) + 1
    
        ) +
    
        MOD( TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 ) +
    
        (
    
          (
    
            (
    
              TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) -
    
              MOD( TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 )
    
            ) -
    
            (
    
              TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) +
    
              (
    
                7 -
    
                (
    
                  MOD( TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 )
    
                )
    
              )
    
            )
    
          ) / 7 * &&WK_WORK_DAY_CNT
    
        )
    
      ) END "Week Day Count"
    
    FROM DUAL
    
    0 讨论(0)
  • 2020-12-04 02:10

    I've updated @JOpuckman's function to take into account that different regions don't always have a weekend of Saturday and Sunday. Here's the code in case anyone else needs to apply this globally;

    DECLARE @FirstDate DateTime
    DECLARE @SecondDate DateTime
    
    SET @FirstDate = '08-20-2012'
    SET @SecondDate = '08-24-2012'
    
    DECLARE @range INT;
    DECLARE @WeekendDayNameStart VARCHAR(50) 
    DECLARE @WeekendDayNameEnd VARCHAR(50)
    
    SET @WeekendDayNameStart = 'FRIDAY'
    SET @WeekendDayNameEnd = (
        SELECT CASE @WeekendDayNameStart
            WHEN 'SUNDAY' THEN 'MONDAY'
            WHEN 'MONDAY' THEN 'TUESDAY'
            WHEN 'TUESDAY' THEN 'WEDNESDAY'
            WHEN 'WEDNESDAY' THEN 'THURSDAY'
            WHEN 'THURSDAY' THEN 'FRIDAY'
            WHEN 'FRIDAY' THEN 'SATURDAY'
            WHEN 'SATURDAY' THEN 'SUNDAY'
        END
    )
    
    DECLARE @NumWorkDays INT
    
    SET @range = DATEDIFF(DAY, @FirstDate, @SecondDate); 
    SET @NumWorkDays = (
    SELECT  
    @range / 7 * 5 + @range % 7 - ( 
        SELECT COUNT(*)  
        FROM ( 
            SELECT 1 AS d 
            UNION ALL SELECT 2  
            UNION ALL SELECT 3  
            UNION ALL SELECT 4  
            UNION ALL SELECT 5  
            UNION ALL SELECT 6  
            UNION ALL SELECT 7 
            ) weekdays 
        WHERE d <= @range % 7  
        AND DATENAME(WEEKDAY, @SecondDate - d) IN (@WeekendDayNameStart, @WeekendDayNameEnd))
    );
    
    -- Calculate whether the current date is a working day
    DECLARE @CurDateExtra INT
    SET @CurDateExtra = 
    (
        CASE DATENAME(WEEKDAY, @SecondDate)
        WHEN @WeekendDayNameStart THEN 0
        WHEN @WeekendDayNameEnd THEN 0
        ELSE 1
        END
    )
    
    SET @NumWorkDays = @NumWorkDays + @CurDateExtra
    SELECT @NumWorkDays
    
    0 讨论(0)
  • 2020-12-04 02:11

    From a previous post:

    DECLARE @StartDate DATETIME
    DECLARE @EndDate DATETIME
    SET @StartDate = '2008/10/01'
    SET @EndDate = '2008/10/31'
    
    
    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)
    
    0 讨论(0)
  • 2020-12-04 02:13

    You should try with a function :

    CREATE FUNCTION TOTAL_WEEKDAYS(date1 DATE, date2 DATE)
    RETURNS INT
    RETURN ABS(DATEDIFF(date2, date1)) + 1
         - ABS(DATEDIFF(ADDDATE(date2, INTERVAL 1 - DAYOFWEEK(date2) DAY),
                        ADDDATE(date1, INTERVAL 1 - DAYOFWEEK(date1) DAY))) / 7 * 2
         - (DAYOFWEEK(IF(date1 < date2, date1, date2)) = 1)
         - (DAYOFWEEK(IF(date1 > date2, date1, date2)) = 7);
    

    Test :

    SELECT TOTAL_WEEKDAYS('2013-08-03', '2013-08-21') weekdays1,
           TOTAL_WEEKDAYS('2013-08-21', '2013-08-03') weekdays2;
    

    Result :

    | WEEKDAYS1 | WEEKDAYS2 |
    -------------------------
    |        13 |        13 |
    
    0 讨论(0)
  • 2020-12-04 02:14

    I have found another way to do calculate the difference, by using only SQL :

    select sysdate - creation_dttm
    - 2 * (to_char(sysdate, 'WW') - to_char(creation_dttm, 'WW'))
    from the_table
    0 讨论(0)
提交回复
热议问题