Count days between two dates, excluding weekends (MySQL only)

后端 未结 5 592
离开以前
离开以前 2020-11-28 16:26

I need to calculate the difference (in days) between two dates in MySQL excluding weekends (Saturday and Sunday). That is, the difference in days minus the number of Saturda

相关标签:
5条回答
  • 2020-11-28 16:34

    You can use a dates table:

    tbl_dates

    dow is 'day of week' in my table. Then your query looks like this:

    SELECT Count(theDate) AS numWeekDays
    FROM tbl_dates
    WHERE theDate >[startDate] And theDate <=[endDate] AND dow <> 1 AND dow <> 7;
    

    In this case, 1 and 7 are Sunday, Saturday, respectively (which is the default) and, of course, you can nest that into another query if you need to calculate this for many startDate(s) and endDate(s).

    0 讨论(0)
  • 2020-11-28 16:43
    Below function will give you the Weekdays, Weekends, Date difference with proper results:
    
    You can call the below function like,
    select getWorkingday('2014-04-01','2014-05-05','day_diffs');
    select getWorkingday('2014-04-01','2014-05-05','work_days');
    select getWorkingday('2014-04-01','2014-05-05','weekend_days');
    
    
    
    
        DROP FUNCTION IF EXISTS PREPROCESSOR.getWorkingday;
        CREATE FUNCTION PREPROCESSOR.`getWorkingday`(d1 datetime,d2 datetime, retType varchar(20)) RETURNS varchar(255) CHARSET utf8
        BEGIN
         DECLARE dow1, dow2,daydiff,workdays, weekenddays, retdays,hourdiff INT;
            declare newstrt_dt datetime;
           SELECT dd.iDiff, dd.iDiff - dd.iWeekEndDays AS iWorkDays, dd.iWeekEndDays into daydiff, workdays, weekenddays
          FROM (
           SELECT
             dd.iDiff,
             ((dd.iWeeks * 2) + 
              IF(dd.iSatDiff >= 0 AND dd.iSatDiff < dd.iDays, 1, 0) + 
              IF (dd.iSunDiff >= 0 AND dd.iSunDiff < dd.iDays, 1, 0)) AS iWeekEndDays
               FROM (
              SELECT  dd.iDiff, FLOOR(dd.iDiff / 7) AS iWeeks, dd.iDiff % 7 iDays, 5 - dd.iStartDay AS iSatDiff,  6 - dd.iStartDay AS iSunDiff
             FROM (
              SELECT
                1 + DATEDIFF(d2, d1) AS iDiff,
                WEEKDAY(d1) AS iStartDay
              ) AS dd
            ) AS dd
          ) AS dd ;
          if(retType = 'day_diffs') then
          set retdays = daydiff; 
         elseif(retType = 'work_days') then
          set retdays = workdays; 
         elseif(retType = 'weekend_days') then  
          set retdays = weekenddays; 
         end if; 
            RETURN retdays; 
            END;
    
    
    Thank You.
    Vinod Cyriac.
    Bangalore
    
    0 讨论(0)
  • 2020-11-28 16:44

    IT my helpful to you

    The bellow logic only show the how many days like

    sun   mon
    
    1      2 .....................
    
    DELIMITER $$
    DROP FUNCTION IF EXISTS `xx`.`get_weekday` $$
    CREATE FUNCTION `xx`.`get_weekday` (first_date date, last_date date, curr_week_day int) RETURNS INT
    BEGIN
    DECLARE days_tot int;
    DECLARE whole_weeks int;
    DECLARE first_day int;
    DECLARE last_day int;
    SET whole_weeks = FLOOR(DATEDIFF(last_date,first_date)/7) ;
    SET first_day = WEEKDAY(first_date) ;
    SET last_day = WEEKDAY(last_date)  ;
    IF curr_week_day  BETWEEN first_day AND  last_day
               AND  last_day > first_day
               OR ( curr_week_day BETWEEN last_day AND first_day
               AND  last_day <  first_day  )
    THEN SET days_tot = whole_weeks + 1;
    ELSE SET days_tot = whole_weeks ;
    END IF;
    RETURN  days_tot;
    END $$
    DELIMITER ;
    
        SELECT
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 0) as mo,
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 1) as tu,
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 2) as we,
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 3) as th,
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 4) as fr,
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 5) as sa,
          `xx`.`get_weekday` ('2009-01-01', '2009-07-20', 6) as su;
    

    Table based query

    ip:

    Weekday count
    2        10
    3         5
    
    
    SELECT WEEKDAY( `req_date_time` ) AS weekday, COUNT( id ) AS id
    FROM `ffffd`
    WHERE (
    `req_date_time` >= '2014-12-01'
    AND `req_date_time` <= '2014-12-31'
    )
    AND WEEKDAY( `req_date_time` ) != '1'
    GROUP BY WEEKDAY( `req_date_time` ) 
    
    0 讨论(0)
  • 2020-11-28 16:48

    Simply try it using a simple 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-11-28 16:49

    Illustration:

    mtwtfSSmtwtfSS
      123456712345   one week plus 5 days, you can remove whole weeks safely
      12345-------   you can analyze partial week's days at start date
      -------12345   or at ( end date - partial days )
    

    Pseudocode:

    @S          = start date
    @E          = end date, not inclusive
    @full_weeks = floor( ( @E-@S ) / 7)
    @days       = (@E-@S) - @full_weeks*7   OR (@E-@S) % 7
    
    SELECT
      @full_weeks*5 -- not saturday+sunday
     +IF( @days >= 1 AND weekday( S+0 )<=4, 1, 0 )
     +IF( @days >= 2 AND weekday( S+1 )<=4, 1, 0 )
     +IF( @days >= 3 AND weekday( S+2 )<=4, 1, 0 )
     +IF( @days >= 4 AND weekday( S+3 )<=4, 1, 0 )
     +IF( @days >= 5 AND weekday( S+4 )<=4, 1, 0 )
     +IF( @days >= 6 AND weekday( S+5 )<=4, 1, 0 )
     -- days always less than 7 days
    
    0 讨论(0)
提交回复
热议问题