Функция MySQL для нахождения количества рабочих дней между двумя датами

Самый короткий, но не поддерживаемый Internet & nbsp; Explorer & nbsp; 8 и ранее:

new Date().toJSON()
37
задан Yada 9 December 2009 в 03:07
поделиться

7 ответов

Создавание немного на @caveman, @bryan-geraghty и @rodger-bagnall's отвечает, мне была нужна версия, которая могла также вычислить назад для несколько "рабочие дни назад" запросов. Эта адаптация работает, когда start_date прежде или после end_date.

SELECT 5 * (DATEDIFF(@E, @S) DIV 7) +
  CASE WHEN @E < @S THEN
    -1 * MID('0123455401234434012332340122123401101234000123450', 7 * WEEKDAY(@E) + WEEKDAY(@S) + 1, 1)
  ELSE
    MID('0123455401234434012332340122123401101234000123450', 7 * WEEKDAY(@S) + WEEKDAY(@E) + 1, 1)
  END

Образец следует из обоих случаев:

+------------+------------+-----------+
| @S         | @E         | wday_diff |
+------------+------------+-----------+
| 2019-11-25 | 2019-10-26 |       -20 |
| 2019-11-25 | 2019-11-28 |         3 |
+------------+------------+-----------+

сообщите мне, находите ли Вы какие-либо ошибки.

0
ответ дан 27 November 2019 в 04:06
поделиться

Thsi работает в Sql Server 2005

Не знаю, подойдет ли он для вас.

DECLARE @StartDate DATETIME,
        @EndDate DATETIME

SELECT  @StartDate = '22 Nov 2009',
        @EndDate = '28 Nov 2009'

;WITH CTE AS(
        SELECT  @StartDate DateVal,
                DATENAME(dw, @StartDate) DayNameVal
        UNION ALL
        SELECT  DateVal + 1,
                DATENAME(dw, DateVal + 1)
        FROM    CTE
        WHERE   DateVal < @EndDate
)
SELECT  COUNT(1)
FROM    (
            SELECT *
            FROM CTE
            WHERE DayNameVal NOT IN ('Sunday','Saturday')
        ) DayVals
0
ответ дан 27 November 2019 в 04:06
поделиться

Проблема, с которой вы столкнетесь с параметром «игнорирование праздников», состоит в том, что в каждой стране будут разные выходные.

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

Я не знаю общих функций, которые делают то, что вы хотите, в mysql

Извините!

1
ответ дан 27 November 2019 в 04:06
поделиться

Поскольку вам нужно будет где-то отслеживать праздники, таблица Calendar кажется подходящей:

CREATE TABLE Calendar
(
     calendar_date     DATETIME     NOT NULL,
     is_holiday        BIT          NOT NULL,
     is_weekend        BIT          NOT NULL,
     CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
)

Вы, конечно, должны заполнить ее всеми датами для любого периода времени, с которым вы могли когда-либо работать в своем приложении . Поскольку в году всего 365 (или 366) дней, переход с 1900 по 2100 не представляет большого труда. Просто убедитесь, что вы загрузили его со всеми датами, а не только с праздниками.

В этот момент запросы, подобные тому, который вам нужен, становятся тривиальными:

SELECT
     COUNT(*)
FROM
     Calendar
WHERE
     calendar_date BETWEEN '2009-01-01' AND '2009-10-01' AND
     is_holiday = 0 AND
     is_weekend = 0

Предостережение: я работаю в основном с MS SQL и не работал с MySQL в течение длительного времени, поэтому вам может потребоваться настроить выше. Например, я даже не помню, есть ли у MySQL тип данных BIT.

13
ответ дан 27 November 2019 в 04:06
поделиться

Решение Yada работает некорректно. Мои изменения:

DELIMITER $$

DROP FUNCTION IF EXISTS `catalog`.`WORKDAYS` $$
CREATE FUNCTION `catalog`.`WORKDAYS` (first_date DATETIME, second_date DATETIME) RETURNS INT
LANGUAGE SQL
DETERMINISTIC

BEGIN

  DECLARE start_date DATE;
  DECLARE end_date DATE;
  DECLARE diff INT;

  IF (first_date < second_date) THEN
    SET start_date = first_date;
    SET end_date = second_date;
  ELSE
    SET start_date = second_date;
    SET end_date = first_date;
  END IF;

  SET diff = DATEDIFF(end_date, start_date);

  RETURN (CASE WHEN DAYNAME(start_date) not in ('Saturday', 'Sunday') && DAYNAME(end_date) = 'Saturday' THEN diff
               WHEN DAYNAME(start_date) not in ('Saturday', 'Sunday') && DAYNAME(end_date) = 'Sunday' THEN (diff - 2)

               WHEN DAYNAME(start_date) = 'Saturday' && DAYNAME(end_date) = 'Sunday' THEN (diff - 1)
               WHEN DAYNAME(start_date) = 'Saturday' && DAYNAME(end_date) = 'Saturday' THEN (diff + 1)
               WHEN DAYNAME(start_date) = 'Sunday' && DAYNAME(end_date) in ('Saturday', 'Sunday') THEN (diff + 1)

               WHEN DAYNAME(start_date) = 'Saturday' && DAYNAME(end_date) not in ('Saturday', 'Sunday') THEN (diff -1)
               WHEN DAYNAME(start_date) = 'Sunday' && DAYNAME(end_date) not in ('Saturday', 'Sunday') THEN (diff + 1)

               WHEN DAYNAME(start_date) not in ('Saturday', 'Sunday') && DAYNAME(end_date) not in ('Saturday', 'Sunday')
                    && WEEKDAY(start_date) > WEEKDAY(end_date) THEN (diff - 2)
               ELSE diff END)
    - (FLOOR(diff / 7) * 2)
    - (CASE WHEN DAYNAME(start_date) = 'Sunday' THEN 1 ELSE 0 END)
    - (CASE WHEN DAYNAME(end_date) = 'Saturday' THEN 1 ELSE 0 END);

END $$

DELIMITER ;
2
ответ дан 27 November 2019 в 04:06
поделиться

Вам нужно будет использовать ] DATEDIFF , чтобы получить количество дней между двумя датами в MySQL. IE:

DATEDIFF(t.date_column_1, t.date_column_2)

Но в остальном Стефан прав - праздники определяются на федеральном и региональном уровнях. Вам нужно создать таблицу, чтобы хранить даты и ссылаться на них в своих вычислениях.

-2
ответ дан 27 November 2019 в 04:06
поделиться
DELIMITER //
DROP FUNCTION IF EXISTS NETWORKDAYS//

CREATE FUNCTION NETWORKDAYS(first_date DATE, second_date DATE)
RETURNS INT
LANGUAGE SQL
DETERMINISTIC
BEGIN
  DECLARE start_date DATE;
  DECLARE end_date DATE;
  DECLARE diff INT;

  IF (first_date < second_date) THEN
    SET start_date = first_date;
    SET end_date = second_date;
  ELSE
    SET start_date = second_date;
    SET end_date = first_date;
  END IF;

  SET diff = DATEDIFF(end_date, start_date);

  RETURN (diff + 1)
    - (FLOOR(diff / 7) * 2)
    - (CASE WHEN DAYNAME(start_date) = 'Sunday' THEN 1 ELSE 0 END)
    - (CASE WHEN DAYNAME(end_date) = 'Saturday' THEN 1 ELSE 0 END);
END//

DELIMITER ;

-- test SELECT Networkdays('2009-12-06', '2009-12-13');

-1
ответ дан 27 November 2019 в 04:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: