Есть несколько вещей, которые вы можете сделать, чтобы значительно повысить эффективность. Во-первых, вы хотите убедиться, что SQL может выполнять простое сравнение при выборе строк, поэтому вы начнете с вычисления строки, соответствующей вашей дате, поскольку ваше поле [Date] является строкой, а не датой.
Во-вторых, заранее подсчитайте минуты в вашей смене (либо 540 для полной смены, либо с уменьшением до 0 ровно в 7 утра), чтобы вы не считали минуты в каждой строке.
В-третьих, когда суммируя для операторов, используйте простую сумму в минутах и рассчитайте эффективность на основе этой суммы и вашей предварительно рассчитанной смены в минутах.
Одно примечание - я использую минуты до FLOAT в моем Например, возможно, это не лучший тип, но он более понятен, чем другие десятичные типы, такие как DECIMAL (18,6) или что-то еще. Выберите что-нибудь, что покажет желаемый масштаб.
В моем примере используется общее табличное выражение для генерации этой строки даты и текущих минут FLOAT, что приятно, потому что оно подходит для прямого запроса, представления, функции, или хранимой процедуры, но вместо этого вы можете ОБЪЯВИТЬ переменные, если захотите.
Путем фильтрации с помощью INNER JOIN в строке [Date] по предварительно вычисленной строке TargetDate, я убеждаюсь, что набор данных сокращен до наименьшего количества записей, прежде чем выполнять какие-либо математические вычисления. Вы определенно захотите использовать INDEX [Date], чтобы поддерживать эту скорость по мере заполнения таблицы.
Все это вместе должно дать довольно быстрый запрос, удачи
with cteNow as ( --Calculate once, up front - date as string, minutes elapsed as FLOAT (or any non-integer)
SELECT CASE WHEN 60*DATEPART(HOUR, GETUTCDATE())+DATEPART(MINUTE, GETUTCDATE()) > 60*21
--4PM in UTC-5, expressed in minutes
THEN CONVERT(float,(16-7)*60) --minutes in (4 PM-7 AM) * 60 minutes/hour
ELSE --Assume nobody is running this at 6 AM, so ELSE = between 7 and 4
CONVERT(float,60*DATEPART(HOUR, GETUTCDATE()) + DATEPART(MINUTE, GETUTCDATE()) - ((7+5)*60))
--Minutes since midnight minus minutes from midnight to 7 AM, shifted by
--UTS offset of 5 hours
END as MinutesToday --Minutes in today's shift so far
, FORMAT(DATEADD(HOUR,-5,GETUTCDATE()),'MM/dd/yyyy') as TargetDate --Date to search for
--as a string so no conversion in every row comparison. Also, index [Date] column
)
SELECT md.Operator, SUM(md.TotalTime) as TotalTime, SUM(md.TotalTime) / MinutesToday as Efficiency
FROM [Master Data] AS md INNER JOIN cteNow as N on N.TargetDate = md.[Date]
GROUP BY md.Operator, MinutesToday
Кстати, вы не делал скидок на обед или бег до 7 утра, поэтому я их тоже игнорировал. Я думаю, что и то, и другое можно решить в cteNOW, не добавляя особой сложности.