6

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

  1. 计算两个日期之间的天数,不包括周末(仅限 MySQL)

  2. 如何在MySQL中计算不包括周末和节假日的日期差异

  3. 计算 SQL 中 2 个日期之间的差异,不包括周末

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

这是一个非常新的概念,但不适用于像@start_date = '2013-08-03' , @end_date = '2013-08-21'Expected ans : 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 ;

请让我知道这会失败的漏洞。欢迎提出任何建议和意见。

4

5 回答 5

17

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

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;

输出:

| 工作日1 | 工作日2 |
-------------------------
| 13 | 13 |

这是DBFiddle演示

于 2013-08-19T01:34:33.180 回答
7

这个查询可以正常工作,上面的所有查询都不能正常工作。尝试这个 :

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
于 2014-10-15T16:35:52.587 回答
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;
于 2017-04-10T23:29:25.573 回答
0

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

例如 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;
    }
于 2013-09-10T12:37:26.380 回答
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);
于 2021-03-07T06:47:22.707 回答