SQL Server 2008 CASE Logic в операторе SELECT - PullRequest
0 голосов
/ 02 апреля 2012

Здравствуйте, гуру SQL Server 2008.

Мне необходимо применить следующие правила к настройке времени начала и окончания рабочего дня для их рабочего дня (почасовые сотрудники) в выписке SELECT. Заранее извиняюсь за незнание SQL.

  1. Правило состоит в том, чтобы установить для их времени начала значение, хранящееся в поле таблицы для этого работника, если они входят в систему или до времени начала (время, хранящееся в столбце starttime работника) и, следовательно, получают кредит для начала в их время начала.

    Если они выходят из системы в течение 10 минут до или в любое время после их времени окончания, сохраненного в столбце для работника, они получают кредит за полный рабочий день, другое значение сохраняется в столбце таблицы работника, в противном случае они штрафуются. некоторый процент от часа, то есть их время выхода из системы округляется до 0,25 часа меньше, чем время выхода из системы. то есть, если они настроены на выход из системы в 4:30 и выход из системы в 4:18, время их выхода составляет 4:15. Если они выходят из системы в 4:20 и выходят из нее в 4:30, время их выхода составляет 4:30.

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

    Вопрос в том, можно ли рассчитать эти правила в операторе SELECT, и если да, могу ли я получить некоторую помощь по коду?

Столбцы, содержащие информацию:

    worker.startime (TIME)
    worker.endtime  (TIME)
    worker.overtimeallowed (BIT)
    worker.workdayhours (decimal (12,2))
    worker.penaltyvalue (decimal (12,2))

Если для этого требуется UDF или хранимая процедура (поскольку я использую Telerik ReportViewer), я не уверен, что это будет поддерживаться, но это, вероятно, другой вопрос.

До сих пор я получал некоторую помощь с применением некоторой логики CASE - вычислением, получает ли работник кредит за 1/2 ланча. Код, который был предоставлен, работает как обещано. Я полагаю, что это может быть расширением этой логики - поэтому я предоставлю код, который у меня есть:

      -- for testing purposes only.
      DECLARE @StartDate AS DateTime
      SET @StartDate = CAST('03/25/2012' AS DATE)
      DECLARE @EndDate AS DateTime
      SET @EndDate = CAST('04/10/2012' AS DATE)

      SELECT 
      w.Firstname 
     ,w.Lastname 
     ,wf.Login
     ,wf.logout
     ,ROUND(CAST(DATEDIFF(MI, wf.Login, wf.Logout) AS DECIMAL)/60,2) 
     - CASE 
        WHEN DATEDIFF(hour, wf.Login, wf.Logout) < w.MinimumHours THEN      
          w.LunchDeduction
        ELSE
        0
       END AS [Hours Credited]
     FROM Workers AS w 
     JOIN Workflow AS wf 
     ON wf.LoggedInWorkerid = w.ID 
     JOIN Roles AS r
     ON w.RoleID = r.RoleID
     WHERE (r.Descript = 'Hourly')
     AND wf.Login >= @StartDate AND wf.Logout <= @EndDate 
     ORDER BY w.Lastname, w.Firstname

1 Ответ

0 голосов
/ 03 апреля 2012

Вот пример выбора, касающийся ограничений, которые вы описали.CTE создают таблицы для целей тестирования.Основной запрос показывает расчеты.Вы работали с датами и датами, поэтому тайны нет.Если вы раньше не использовали%, то для округления времени до 15 минут используется оператор по модулю .

;with worker (ID, overtime, startTime, endTime) as
(
    select 1, 1, CAST ('08:30' as time), CAST ('16:30' as time)
    union all
    select 2, 0, CAST ('08:30' as time), CAST ('16:30' as time)
    union all
    select 3, 0, CAST ('08:30' as time), CAST ('16:30' as time)
),
-- Test table of workflows
wf (workerID, login, logout) as
(
    select 1, CAST ('2012-03-11 08:20' as datetime), CAST ('2012-03-11 19:33' as datetime)
    union all
    select 2, CAST ('2012-03-11 08:50' as datetime), CAST ('2012-03-11 16:20' as datetime)
    union all
    select 3, CAST ('2012-03-11 08:22' as datetime), CAST ('2012-03-11 16:18' as datetime)
)
select wf.workerID,
  wf.login,
  wf.logout,
  --  if starttime > login return startTime else login
  case when DATEDIFF(MI, w.startTime, cast (wf.login as time)) < 0 
    then cast(CAST (wf.login AS date) AS datetime) + w.startTime
    else wf.login
  end roundedLogin,
  case when w.overtime = 1 -- Round to 15 minutes whenever finished
         OR
         -- Round to 15 minutes if left ten or more minutes before endTime
            DATEDIFF(MI, cast (wf.logout as time), dateadd (MI, -10, w.endTime)) > 0 
    then dateadd (MI, -(DATEPART (MI, wf.logout) % 15), wf.logout)
    -- stop at endTime if overtime = 0 OR left job at apropriate time
    else cast(CAST (wf.logout AS date) AS datetime) + w.endTime
  end roundedLogout
from worker w 
  inner join wf 
     on w.ID = wf.workerID

При таком подходе возникнет проблема.Когда вы начнете интегрировать математику в исходный запрос, вы заметите, что вам нужно снова написать выражения для оценки округлого логина и округлого лога, чтобы вычислить оплачиваемые часы.Вы не можете повторно использовать псевдоним, определенный в той же области, но вы можете создать производную таблицу или представление или даже вычисляемые поля.Представление, возвращающее столбцы из рабочих процессов и все дополнительные выражения, вероятно, будет наилучшим.

Использование этого представления в других запросах упростит задачу, заключив логику в одном месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...