Другой подход заключается в создании таблицы со строкой в ней для каждой минуты дня, 1440 строк.
CREATE TABLE ShiftCheck
(
id int,
MyTime datetime not null,
ShiftNumber int not null,
ShiftName char(3) not null
CONSTRAINT [PK_ShiftCheck] PRIMARY KEY CLUSTERED
(
[id] ASC
)
)
Заполните эту таблицу оператором, похожим на этот
; WITH DateIntervalsCTE AS
(
SELECT 0 i, cast('1/1/1900' as datetime) AS Date
UNION ALL
SELECT i + 1, DATEADD(MINUTE, i,cast('1/1/1900' as datetime) )
FROM DateIntervalsCTE
WHERE DATEADD(MINUTE, i, cast('1/1/1900' as datetime) ) < cast('1/2/1900' as datetime)
)
SELECT
ROW_NUMBER() over (order by Date),
Date,
CASE
WHEN convert(varchar, Date, 108) >= '06:45:00' and convert(varchar, Date, 108) < '14:45:00' then 1
WHEN convert(varchar, Date, 108) >= '14:45:00' and convert(varchar, Date, 108) < '23:00:00' then 2
ELSE 3
END,
CASE
WHEN convert(varchar, Date, 108) >= '06:45:00' and convert(varchar, Date, 108) < '14:45:00' then 'AM'
WHEN convert(varchar, Date, 108) >= '14:45:00' and convert(varchar, Date, 108) < '23:00:00' then 'PM'
ELSE 'NOC'
END
FROM DateIntervalsCTE
OPTION (MAXRECURSION 32767);
Затем вам просто нужно присоединиться к таблице ShiftCheck за раз.Для заполнения таблицы необходимо только рассчитать, сколько времени происходит за смену.
Скалярные функции , как и те, что перечислены в вашем вопросе, выполняются для каждой строки в данном запросе.Например,
Select *,[dbo].[DateToNocShift](ShiftDate)
from myTable
функция будет выполняться для каждой строки в myTable, которая в определенный момент (субботнее утро, когда вы спите) будет очень медленной.В заключение, это в конечном итоге станет проблемой производительности, и в конце концов кто-то захочет увидеть слово 1, 2, 3 для названия смены.Это решение решит оба из них, а также заставит поиск вместо вычисления.
* Если это не достаточно точно, поместите строку для каждой секунды дня (24 * 60 * 60 = 86400 строк, все еще не так уж много для сервера sql) * Я взял генерирование sql из здесь