SQL Сервер: измерение эффективности в реальном времени оператором - PullRequest
0 голосов
/ 08 мая 2020

Я работал над кодом SQL для измерения эффективности в реальном времени некоторых производственных данных. Вот краткая справка:

Операторы будут вводить данные для определенных c подсборок. Эти данные выглядят примерно так:

ID                      PO      W/S     Status      Operator            TotalTime   Date 
60129515_2000_6_S025    107294  S025    Completed   A                   38          05/08/2020
60129515_2000_7_S025    107294  S025    Completed   A                   46          05/08/2020
60129515_2000_8_S025    107294  S025    Completed   A                   55          05/08/2020
60129515_2025_6_S020    107295  S020    Completed   B                   58          05/08/2020
60129515_2025_7_S020    107295  S020    Completed   B                   47          05/08/2020
60129515_2025_8_S020    107295  S020    Completed   B                   45          05/08/2020
60129515_2000_1_S090    107294  S090    Completed   C                   33          05/08/2020
60129515_2000_2_S090    107294  S090    Completed   C                   34          05/08/2020
60129515_2000_3_S090    107294  S090    Completed   C                   21          05/08/2020

Соответствующими столбцами являются Operator, TotalTime и Date (обратите внимание, что дата сохраняется как varchar(50), потому что она лучше работает с Microsoft PowerApps. туда).

Что мне нужно сделать, это:

  • Суммировать сумму «TotalTime», сгруппированную оператором
  • Рассчитать прошедшее время на основе условия:
    • Если между 7:00 и 16:00, рассчитать время, прошедшее с 7:00 текущего дня
    • Если после 16:00, вернуть общее время между 7:00 и 16:00 текущего дня
  • Разделите СУММУ (TotalTime) на TimeElapsed (также известный как первый элемент списка / второй элемент списка), чтобы получить приблизительную оценку отработанных рабочих часов по сравнению с часами, проведенными за день.

Это вычисление будет изменяться каждый раз при выполнении запроса. Это позволит приложению Microsoft PowerApp, обрабатывающему этот запрос, обновлять sh показатель эффективности в реальном времени. Я уже попробовал это сделать - см. Ниже:

SELECT
    md.Operator,
    CASE 
       WHEN DATEADD(HOUR, -5, GETUTCDATE()) > CONVERT(DATETIME, CONVERT(DATE, DATEADD(HOUR, -5, GETUTCDATE()))) + '7:00' AND GETDATE() < CONVERT(DATETIME, CONVERT(DATE, DATEADD(HOUR, -5, GETUTCDATE()))) + '15:45' 
          THEN (SUM(isNull(md.TotalTime, 0)) + SUM(isNull(md.DelTime, 0))) * 1.0 / DATEDIFF(MINUTE, CONVERT(DATETIME, CONVERT(DATE, DATEADD(HOUR, -5, GETUTCDATE()))) + '7:00' , DATEADD(HOUR, -5, GETUTCDATE())) * 100.0
          ELSE (SUM(isNull(md.TotalTime, 0)) + SUM(isNull(md.DelTime, 0))) / 420 * 100.0
    END AS OpEfficiency
FROM 
    [Master Data] AS md
WHERE 
    md.[Date] = CONVERT(varchar(50), DATEADD(HOUR, -5, GETUTCDATE()), 101)
GROUP BY 
    md.Operator

Примечание : DelTime - это другой столбец, касающийся времени задержки. Я также конвертирую время UT C, чтобы избежать проблем с часовым поясом при переходе на PowerApps.

Однако это ужасно неэффективно. Я предполагаю, что это потому, что Date нужно каждый раз преобразовывать в datetime. Было бы лучше, если бы у меня был вычисляемый столбец, в котором уже была преобразована дата? Или есть лучший способ рассчитать время, прошедшее с определенного времени?

Заранее спасибо.

1 Ответ

0 голосов
/ 09 мая 2020

Есть несколько вещей, которые вы можете сделать, чтобы значительно повысить эффективность. Во-первых, вы хотите убедиться, что 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, не добавляя особой сложности.

...