2012-03-18 13 views
3

Мне нужно рассчитать разницу (в днях) между двумя датами в MySQL, исключая выходные (субботу и воскресенье). То есть разница в днях минус количество суббот и воскресенье между ними.Количество дней между двумя датами, исключая выходные (только для MySQL)

На данный момент, я просто считать дни, используя:

SELECT DATEDIFF('2012-03-18', '2012-03-01') 

Это возвращение 17, но я хочу, чтобы исключить выходные, так что я хочу 12 (потому что третья и четвёртая, 10 и 11 и 17-й в выходные дни).

Я не знаю с чего начать. Я знаю о функции WEEKDAY() и всех связанных, но я не знаю, как их использовать в этом контексте.

+1

@xdazz У меня нет функции, чтобы разделить неделю между двумя датами в MySQL. 'DATEDIFF' работает только в дни, а не на неделе, например DATEDIFF в TSQL. –

+0

@xdazz, если честно, это другая СУРБД, однако это возможный дубликат функции [MySQL, чтобы найти количество рабочих дней между двумя датами] (http://stackoverflow.com/questions/1828948/mysql-function -to-find-the-number-of-work-days-between-two-dates) – Ben

+0

Вы хотите также исключить праздники? – biziclop

ответ

4

Иллюстрация:

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) 

псевдокод:

@S   = start date 
@E   = end date, not inclusive 
@full_weeks = floor((@[email protected])/7) 
@days  = (@[email protected]) - @full_weeks*7 OR (@[email protected]) % 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

Думаю, я понял. Я попробую и дам вам знать. –

+2

Есть ли ошибка в коде? Сразу после SELECT не должно быть '@ full_weeks * 5' вместо' @ full_weeks * 2'? –

+0

Да, я пропустил выходные с рабочими днями, извините. – biziclop

1
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 
6

Просто попробуйте, используя простую функцию:

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

Тест:

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

Результат:

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

IT мой полезный для вас

Рева логик только показывает, сколько дней как

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; 

Таблица запрос на основе

IP:

Weekday count 
2  10 
3   5 


SELECT WEEKDAY(`req_date_time`) AS weekday, COUNT(id) AS id 
FROM `ddd` 
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

Вы также можете сделать это с помощью запросов, но вам понадобится таблица дат, которая охватывает диапазоны дат. В любом случае рекомендуется создавать таблицы дат для использования во всех ваших проектах.

Чтобы создать таблицу дат, все, что вы делаете, это генерация длинного списка дат (EXCEL - удобный метод, но есть другие способы) и импортировать их в таблицу. Затем используйте эти даты в сочетании с различными функциями даты, чтобы получить «день недели», «месяц», «год» и т. Д., И сохранить все это в таблице с датами, например:

tbl_dates

dates table

Дау 'день недели' в моей таблице. Тогда ваш запрос выглядит следующим образом:

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

В этом случае, 1 и 7 являются воскресенье, суббота, соответственно (это значение по умолчанию) и, конечно же, вы можете гнездо, что в другой запрос, если вам нужно вычислить это для многих startDate (s) и endDate (s).

Смежные вопросы