mysql-function计算2个日期之间的天数,不包括周末

时间:2013-08-18 18:05:33

标签: mysql

我搜索了很多例子,我得到了很好的例子:

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

  2. How to count date difference excluding weekend and holidays in MySQL

  3. Calculate diffference between 2 dates in SQL, excluding weekend days

  4. 但是没有得到最有希望的解决方案,所以我可以在我的mysql函数中使用来查询行的十万行。

    这个是一个非常新的概念,但是对于像@start_date = '2013-08-03' , @end_date = '2013-08-21'预期的答案:13,它仅给出12,

    等输入不起作用
    SELECT 5 * (DATEDIFF(@end_date, @start_date) DIV 7) + MID('0123444401233334012222340111123400012345001234550', 7 * WEEKDAY(@start_date) + WEEKDAY(@end_date) + 1, 1);
    

    所以我试图自己做 -

    Concept : 
    Input : 1. period_from_date  - from date
            2. period_to_date    - to date
            3. days_to_exclude   - mapping : S M T W TH F Sat   =>  2^0 + 2^6
              (sat and sun to exclude)       ^ ^ ^ ^ ^  ^  ^
                                             0 1 2 3 4  5  6
    

    DELIMITER $$
    
    USE `db_name`$$
    
    DROP FUNCTION IF EXISTS `FUNC_CALC_TOTAL_WEEKDAYS`$$
    
    CREATE DEFINER=`name`@`%` FUNCTION `FUNC_CALC_TOTAL_WEEKDAYS`( period_from_date DATE, period_to_date DATE, days_to_exclude INT ) RETURNS INT(11)
    BEGIN
    
    DECLARE period_total_num_days      INT DEFAULT 0;
    DECLARE period_total_working_days  INT DEFAULT 0;
    DECLARE period_extra_days          INT DEFAULT 0;
    DECLARE period_complete_weeks      INT DEFAULT 0;
    DECLARE extra_days_start_date      DATE DEFAULT '0000-00-00';
    DECLARE num_days_to_exclude        INT DEFAULT 0;
    DECLARE start_counter_frm          INT DEFAULT 0;
    DECLARE end_counter_to             INT DEFAULT 6;
    DECLARE temp_var                   INT DEFAULT 0;
    
    # if no day to exclude return date-diff only
    IF days_to_exclude = 0 THEN
        RETURN DATEDIFF( period_to_date, period_from_date ) + 1 ;
    END IF;
    
    # get total no of days to exclude
    WHILE start_counter_frm <= end_counter_to  DO
       SET temp_var = POW(2,start_counter_frm) ;
       IF (temp_var  & days_to_exclude) = temp_var  THEN
                SET num_days_to_exclude = num_days_to_exclude + 1;
       END IF;
     SET start_counter_frm = start_counter_frm + 1;
    END WHILE;
    
    # Get period days count
    SET period_total_num_days       = DATEDIFF( period_to_date, period_from_date ) + 1 ;
    SET period_complete_weeks       = FLOOR( period_total_num_days /7 );
    SET period_extra_days           = period_total_num_days  - ( period_complete_weeks * 7 );
    SET period_total_working_days   = period_complete_weeks * (7 - num_days_to_exclude);
    SET extra_days_start_date       = DATE_SUB(period_to_date,INTERVAL period_extra_days DAY);
    
    # get total working days from the left days
    WHILE period_extra_days > 0 DO
        SET temp_var = DAYOFWEEK(period_to_date) -1;
    
        IF POW(2,temp_var) & days_to_exclude != POW(2,temp_var) THEN
            SET period_total_working_days = period_total_working_days +1;
        END IF;
    
        SET period_to_date = DATE_SUB(period_to_date,INTERVAL 1 DAY);
        SET period_extra_days = period_extra_days -1;
    
    END WHILE; 
    
    RETURN period_total_working_days;
    END$$
    
    DELIMITER ;
    

    请告诉我这会失败的漏洞。打开任何建议和评论。

5 个答案:

答案 0 :(得分:15)

更新:如果你需要两个日期之间的工作日,你可以像这样得到它

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);

注意:如果您切换开始date1和结束date2日期,该功能仍然有用。

样本用法:

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

输出:

| WEEKDAYS1 | WEEKDAYS2 |
-------------------------
|        13 |        13 |

这是 SQLFiddle 演示

答案 1 :(得分:6)

此查询将正常运行,上述所有查询都无法正常运行。试试这个:

SELECT ((DATEDIFF(date2, date1)) -
        ((WEEK(date2) - WEEK(date1)) * 2) -
        (case when weekday(date2) = 6 then 1 else 0 end) -
        (case when weekday(date1) = 5 then 1 else 0 end)) as DifD

像这样测试:

SELECT ((DATEDIFF('2014-10-25', '2014-10-15')) -
            ((WEEK('2014-10-25') - WEEK('2014-10-15')) * 2) -
            (case when weekday('2014-10-25') = 6 then 1 else 0 end) -
            (case when weekday('2014-10-15') = 5 then 1 else 0 end)) as DifD

结果:

DifD    
8

答案 2 :(得分:1)

我用这个。意味着没有功能,因此可以在视图中使用:

select 
datediff(@dateto, @datefrom) + 
datediff(@datefrom, 
    date_add(@datefrom, INTERVAL 
     floor(datediff(@dateto, @datefrom) / 7) day)) * 2
- case
    when weekday(@dateto) = 6 then 2
    when weekday(@dateto) = 5 then 1
    when weekday(@dateto) < weekday(@datefrom) then 2
    else 0 
end;

答案 3 :(得分:0)

有一个类似的问题,我使用PHP删除周末,需要知道开始日期和天数:

EG SQL:

  SELECT DAYOFWEEK(`date1`) AS `startday`, TIMESTAMPDIFF(DAY, `date1`, `date2`) AS `interval` FROM `table`

然后通过PHP函数运行结果:

    function noweekends($startday, $interval) {
        //Remove weekends from an interval
        $wecount = 0; $tmp = $interval;
        while($interval/7 > 1) { $interval-=7; $wecount++; }
        if($interval+$startday > 5) $wecount++;
        $interval = $tmp-($wecount*2);
        return $interval;
    }

答案 4 :(得分:0)

仅排除星期日

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
     - (DAYOFWEEK(IF(date1 < date2, date1, date2)) = 1);