T-sql функція розрахунку кількості робочих годин між двома датами з урахуванням бізнес-календаря -

Отже, готова функція розрахунку кількості робочих годин між двома датами. Дану функцію ми самі використовуємо в звітах по підтримці.

Перш розповім як зберігаються дані в бізнес-календарі.
Бізнес календар має 3 секції (краще подивитися в CardManager)

1. Основна інформація (тільки одне поле Name, зрозуміло для чого воно потрібно)
2. Року (Years). Має отдного поле Year в якому вказується рік
2.1 Підсекція Days. Має поля Day - номер дня від початку року і Type тип
2.1.1 Підсекція WorkTime. Поля StartTime і EndTime - часовий діапазон
3. DefaultTimeSettings. Поля StartTime і EndTime - часовий діапазон

У календарі можна робити кілька налаштувань.

1. настроках робочого часу за замовчуванням.
Ця установка буде зберігатися в секції DefaultTimeSettings. Рядки секції будуть містити тимчасові інтервали.

3. Налаштування календаря за умовчанням
Дані настройки будуть зберігатися в тій же секції Years (аналогічно п.2), але в році 1796.

Якщо для конкретного дня немає збережених налаштувань, береться наступне робочий час:
Робочі дні: з понеділка по п'ятницю
Робочий графік: з 9:00 до 13:00, та з 14:00 до 18:00

Скрипт складається з 3х функцій
1. Перевірка, чи є даний день робочим FIsWorkTime
2. Ф-ція розрахунку тривалості робочого часу для одного дня FGetDayDuration
3. Основна ф-ція розрахунку тривалості між двома датами FBusinessHours2

Алгоритм наступний.
Ф-ція FBusinessHours2 обчислює за допомогою FGetDayDuration тривалість робочого часу в перший день інтервалу (до кінця першого робочого дня). Тривалість робочого часу в останній день інтервалу (від початку робочого дня до кінцевого часу), і тривалість у всіх днях між початковим і кінцевим.

Оскільки дані зберігаються для конкретних днів, а не для всіх, то єдиним способом підрахунку є перебір всіх днів в циклі. Це вкрай не оптимальний спосіб. Альтернативним варіантом було б періодичне створення "карти" робочого розкладу для всіх днів в інтервалі, із зберіганням часу в UTC в окремій таблиці. Тоді розрахунок тривалості можна буде виконати декількома SELECT'амі за частки секунди.

Ф-ція FBusinessHours2 може повертати дані в хвилинах або годинах в залежності від 3-го параметра @Mode.