简体   繁体   中英

Calculating Percentages with SUM and Group by

I am trying to create an Over Time Calculation based on some set criteria. It goes as follows.

Overtime is posted on any day that is over 8 hrs but an employee has to reach 40 total hrs first and the calculation starts at the 1st day moving forward in the week. The Overtime is calculated based on the percentage taken of the SUM total of the cost codes worked.

First you have to find the percentage of each cost code worked for the entire week per employee id. See Example below

Then each day that is Over 8 hrs you take the time on that code for the day and multiply it by the calculated percentage. At the end of the week the regular hours must total 40hrs if they have gone over 40 for the week. See below example

CREATE TABLE [Totals](
    [Day] nvarchar (10) null,
    [EmployeeID] [nvarchar](100) NULL,
    [CostCode] [nvarchar](100) NULL,
    [TotalTime] [real] NULL,)

INSERT  Into Totals (day,employeeid, CostCode, TotalTime) VALUES
('1','1234','1', 2),
('1','1234','2', 7.5),
('2','1234','1', 1.5),
('2','1234','2', 8),
('3','1234','1', 1),
('3','1234','2', 6),
('4','1234','1', 2),
('4','1234','2', 8),
('5','1234','1', 2),
('5','1234','2', 8),
('1','4567','1', 2),
('1','4567','2', 8.5),
('2','4567','1', 1.5), 
('2','4567','2', 7.6),
('3','4567','1', 1),
('3','4567','2', 5),
('4','4567','1', 2),
('4','4567','2', 8),
('5','4567','1', 2),
('5','4567','2', 8)

To get the percentage of each cost Worked it is the SUM total time of each cost per week / SUM total time of the entire week

   SELECT employeeid,CostCode,SUM(totaltime) As TotalTime ,
   ROUND(SUM(Totaltime) / (select SUM(TotalTime) from Totals where employeeid = '1234') * 100,0) as Percentage
    from Totals WHERE EmployeeID = '1234' group by EmployeeID, CostCode

Percentage Calculated for the Week by Cost = 18% worked on Cost 1 and 82% on Cost 2

I would like to take the percentage results for the week and calculate the total time each day in the query

Results Example Day 1: for EmployeeID 1234

Day CostCode RegTime OverTime 
 1     1        1.73     .27      
 1     2        6.27    1.23

After editing i get your result, try this:

select calc.*
--select [day], CostCode, EmployeeID
--, CPr * DayEmpRT RegTime_old
, TotalTime - CPr * DayEmpOT RegTime
, CPr * DayEmpOT OverTime
from ( 
  select Agr.*
  --, round(EmpC1T / EmpT, 2) C1Pr
  --, round(1 - (EmpC1T / EmpT), 2) C2Pr
  , round(EmpCT / EmpT, 2) CPr
  , case when DayEmpT > 8 then 8 else DayEmpT end DayEmpRT
  , case when DayEmpT > 8 then DayEmpT - 8 else 0 end DayEmpOT
  from (
    select Totals.*
    , SUM(TotalTime) over (partition by EmployeeID, [day]) DayEmpT
    --, SUM(case when CostCode = 1 then TotalTime end) over (partition by EmployeeID) EmpC1T
    , SUM(TotalTime) over (partition by EmployeeID, CostCode) EmpCT
    , SUM(TotalTime) over (partition by EmployeeID) EmpT
    from Totals
    WHERE EmployeeID = '1234' ) Agr ) calc
order by 1,2,3

here is simplest way to calculate this:

select calc.*
, TotalTime * pr4R RegTime
, TotalTime * pr4O OverTime
from(
  select Agr.*
  , case when EmpT > 40 then round(40/EmpT, 2) else 1 end pr4R
  , case when EmpT > 40 then round(1 - 40/EmpT, 2) else 1 end pr4O
  from (
    select Totals.*
    , SUM(TotalTime) over (partition by EmployeeID) EmpT
    from Totals
    WHERE EmployeeID = '1234' ) Agr ) calc

but be watch on day 3, because there is only 7h. The 1st query calculate days separately and live day 3. The 2nd query scale all hours. it could be another one, that calculate all emp rows but scale separatly RegTime and OverTime, with exception on day where is no 8h and increment it to 8h from OverTime.

This should help you get started...

-- % based on hours worked for each code on a DAILY basis (The original 21% in the question was based on this)
SELECT
T.EmployeeId,
T.Day,
T.CostCode,
T.TotalTime,
CAST(100.0 * T.TotalTime / X.DailyHours AS DECIMAL(10,2)) AS PercentageWorked
FROM #Totals T
INNER JOIN (
    SELECT
    EmployeeId,
    Day,
    SUM(TotalTime) AS DailyHours
    FROM #Totals
    GROUP BY EmployeeId, Day
) X ON X.EmployeeId = T.EmployeeId AND X.Day = T.Day


-- % based on hours worked for each code on a WEEKLY basis (The revised question)
SELECT
T.EmployeeId,
T.CostCode,
SUM(T.TotalTime) AS TotalTime,
CAST(100.0 * SUM(T.TotalTime) / X.WeeklyHours AS DECIMAL(10,2)) AS PercentageWorked
FROM #Totals T
INNER JOIN (
    SELECT
    EmployeeId,
    SUM(TotalTime) AS WeeklyHours
    FROM #Totals
    GROUP BY EmployeeId
) X ON X.EmployeeId = T.EmployeeId 
GROUP BY 
T.EmployeeId,
T.CostCode, 
X.WeeklyHours

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM