2015-07-09 6 views
1

Если вы видите здесьКак сделать дело в SQL, как если ELSEIF заявление

CREATE TABLE timesheet 
    ([username] varchar(31), [local_date] datetime, [hours] numeric, [wday] varchar(31)) 
; 

INSERT INTO timesheet 
    ([username], [local_date], [hours],[wday]) 
VALUES 
    ('[email protected]', '1915-05-24 19:00:00', 3.75,'Sun'), 
    ('[email protected]', '1915-05-25 19:00:00', 11,'Mon'), 
    ('[email protected]', '1915-05-26 19:00:00', 10.25,'Tue'), 
    ('[email protected]', '1915-05-27 19:00:00', 13,'Wed'), 
    ('[email protected]', '1915-05-28 19:00:00', 13,'Thu'), 
    ('[email protected]', '1915-05-29 19:00:00', 14,'Fri'), 
    ('[email protected]', '1915-05-30 19:00:00', 9,'Sat'), 
    ('[email protected]', '1915-05-31 19:00:00', 12,'Sun'), 
    ('[email protected]', '1915-06-01 19:00:00', 12.5,'Mon') 
; 

select 
    username 
    , datepart(week,local_date) as Week 
    , sum(hours) total 
    , case when sum(hours) <= 40 then sum(hours) else 40 end as Regulartime 
    , case when sum(hours) > 40 then sum(hours) - 40 else 0 end as Overtime 
from timesheet 
group by username, datepart(week, local_date); 

SQL Fiddle

У меня есть таблица с расписания часов и дней. Мне нужно рассчитать регулярное время. Регулярное время должно быть только в будние часы и должно быть < = 40. Если его выходные или> 40, то это сверхурочное время. Как это сделать в SQL?

ответ

3
CREATE TABLE #timesheet 
     ([username] varchar(31), [local_date] datetime, [hours] numeric(6,2), [wday] varchar(31)) 

    INSERT INTO #timesheet 
     ([username], [local_date], [hours],[wday]) 
    VALUES 
     ('[email protected]', '2015-05-24 19:00:00', 3.75 ,'Sun'), 
     ('[email protected]', '2015-05-25 19:00:00', 11 ,'Mon'), 
     ('[email protected]', '2015-05-26 19:00:00', 10.25,'Tue'), 
     ('[email protected]', '2015-05-27 19:00:00', 13 ,'Wed'), 
     ('[email protected]', '2015-05-28 19:00:00', 13 ,'Thu'), 
     ('[email protected]', '2015-05-29 19:00:00', 14 ,'Fri'), 
     ('[email protected]', '2015-05-30 19:00:00', 9 ,'Sat'),  
     ('[email protected]', '2015-05-31 19:00:00', 12 ,'Sun'), 
     ('[email protected]', '2015-06-01 19:00:00', 12.5 ,'Mon') 

    select 
     username 
     , datepart(week,local_date) as Week 
     , sum(hours) total 
     , case when sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) > 40 
       then 40 
       else sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) end as RegHours 
     , sum(case when DATENAME(dw, local_date) IN ('Saturday', 'Sunday') then hours else 0 end) + 
      case when sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) > 40 
       then sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) - 40 else 0 end as OTHours 
    from #timesheet 
    group by username, datepart(week, local_date) 

    DROP TABLE #timesheet 

username      Week total RegHours OTHours 
[email protected] 22 74.00 40.00  34.00 
[email protected] 23 24.50 12.50  12.00 
+0

Я отправил свой ответ, потому что я неправильно интерпретировал этот на первый. Глядя снова, я вижу, что моя существенно похожа. Если вы добавите таблицу результатов в конец этого, я удалю мой. –

+1

Секунды часов изменены на числовые (6,2) Даты, измененные с 1915 по 2015 год Удаленный подзапрос – Lori

0

Если я правильно понимаю, RegularTime - это общее количество часов M-F до 40 часов.
OverTime - общее количество часов - 40, если общее количество часов составляет 40.
Таким образом, вам не нужно будет проверять день в Overtime, потому что если они будут работать более 40 часов на рабочей неделе, дополнительные часы будут по-прежнему рассматриваться со временем.

select 
    username 
    , datepart(week,local_date) as Week 
    , sum(hours) total 
    , Case When sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) <= 40 
      Then sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) Else 40 End as RegularTime 
    , Case When sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) > 40 
      Then (sum(case when DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') then hours else 0 end) - 40) 
       + sum(case when DATENAME(dw, local_date) IN ('Saturday', 'Sunday') then hours else 0 end) 
      Else sum(case when DATENAME(dw, local_date) IN ('Saturday', 'Sunday') then hours else 0 end) End as Overtime 
from timesheet 
group by username, datepart(week, local_date); 

ВЫВОД:

username      Week total RegularTime OverTime 
[email protected] 22  65  40   25 
[email protected] 23  34  25   9 
+0

спасибо за ответы. –

+0

Я хочу избежать подзапросов. Я могу использовать ответ от Doolius, но как я могу убедиться, что время рекурата <= 40 –

+0

i означало Regulartime <= 40 –

1

мне легче рассуждать о запросе, если я отвлекаюсь выходные/будний часть с КТР первым:

WITH HoursBuckets As 
(
    SELECT username 
     , DATEPART(week,local_date) As Week 
     , SUM(hours) total 
     , SUM(CASE WHEN DATENAME(dw, local_date) NOT IN ('Saturday', 'Sunday') THEN hours ELSE 0 END) As WeekDay 
     , SUM(CASE WHEN DATENAME(dw, local_date) IN ('Saturday', 'Sunday') THEN hours ELSE 0 END) As WeekEnd 
    FROM timesheet 
    GROUP BY username, DATEPART(week, local_date) 
) 
SELECT username, Week, Total, 
    CASE WHEN Weekday > 40 THEN 40 ELSE Weekday END As RegularTime, 
    CASE WHEN Weekday > 40 THEN Weekday - 40 ELSE 0 END + WeekEnd As OverTime 
FROM HoursBuckets; 

Результаты:

 
username      Week Total RegularTime OverTime 
[email protected] 22  65  40   25 
[email protected] 23  34  25   9
0

Это решение отличается только тем, что она имеет все шаги, разбитые подзапросов, чтобы вы могли видеть то, что происходит на каждом шагу:

CREATE TABLE timesheet 
    ([username] varchar(31), [local_date] datetime, 
    [hours] numeric(6,2), [wday] varchar(31)); 

INSERT INTO timesheet 
    ([username], [local_date], [hours],[wday]) 
VALUES 
    ('[email protected]', '2015-05-24 19:00:00', 3.75,'Sun'), 
    ('[email protected]', '2015-05-25 19:00:00', 11,'Mon'), 
    ('[email protected]', '2015-05-26 19:00:00', 10.25,'Tue'), 
    ('[email protected]', '2015-05-27 19:00:00', 13,'Wed'), 
    ('[email protected]', '2015-05-28 19:00:00', 13,'Thu'), 
    ('[email protected]', '2015-05-29 19:00:00', 14,'Fri'), 
    ('[email protected]', '2015-05-30 19:00:00', 9,'Sat'), 
    ('[email protected]', '2015-05-31 19:00:00', 12,'Sun'), 
    ('[email protected]', '2015-06-01 19:00:00', 12.5,'Mon') ; 

select 
    username, 
    week, 
    sum_weekend_hours + sum_weekday_hours as total, 
    case when sum_weekday_hours <= 40 then sum_weekday_hours else 40 end as Regulartime, 
    sum_weekend_hours + 
    case when sum_weekday_hours <= 40 then 0 
    else sum_weekday_hours - 40 end as Overtime 
from 
    (select 
    username, 
    Week, 
    sum(weekEndHours) as sum_weekend_hours, 
    sum(weekDayHours) as sum_weekday_hours 
    from 
    (select 
     username, 
     local_date, 
     hours, 
     wday, 
     datepart(week,local_date) as Week, 
     datepart(weekday,local_date) as weekday, 
     case when datepart(weekday,local_date) in (1,7) then hours else 0 end as weekEndHours, -- sat, sun 
     case when not(datepart(weekday,local_date) in (1,7)) then hours else 0 end as weekDayHours -- sat, sun 
     from 
     timesheet) t 
    group by 
    username, 
    Week) g; 

SQL Fiddle