Calculating over time hours for employees against their contract hours - sql

Calculating over time hours for employees against their individual contract hours, the percentage an employee has worked overtimes as well as how many worked more than 10% overtime.
Sample data is here:
http://sqlfiddle.com/#!9/a2ba19/2/0
Sample data has:
ID- Employee ID
PROJECT - Project code Employee belongs to
SEGMENT - are the projects an employee is working on
SEG_DESC- description of the projects
CONTRACT HRS- is the individual contract hrs the employee is hired to do
HOURS - are the hours an employee has worked in a segment
TEAM- Employee belongs to
END_OF_WEEK - data is collected weekly
I need the
the percentage an employee has worked overtime
how many employees have worked more than 10% overtime
Once these calculations are done, I need to be able to visualise the data in Power BI.
I have actually achieved all I needed to do in Power BI - but the dashboard is extremely slow and therefore not viable. Therefore, the overtime calculations need all to already happen in SQL.
How can I do this?
Please see how it should look:

Looking at your desired output it appears you just need a simple sum of the time per team per Id, in which case the following produces your desired
result:
with ot as (
select *, Sum(hours) over(partition by project, id, team) TimeWorkedPerWeek
from workinghours
)
select *,
TimeWorkedPerWeek-[contract hrs] OverTimeHours,
(TimeWorkedPerWeek)/[CONTRACT HRS]-1 [%Overtime],
case when TimeWorkedPerWeek> [CONTRACT HRS]*1.1 then 1 else 0 end [Overtime > 10%]
from ot
order by id, team
DBFiddle example

Related

Finding the initial sampled time window after using SAMPLE BY again

I can't seem to find a perhaps easy solution to what I'm trying to accomplish here, using SQL and, more importantly, QuestDB. I also find it hard to put my exact question into words so bear with me.
Input
My real input is different of course but a similar dataset or case is the gas_prices table on the demo page of QuestDB. On https://demo.questdb.io, you can directly write and run queries against some sample database, so it should be easy enough to follow.
The main task I want to accomplish is to find out which month was responsible for the year's highest galon price.
Output
Using the following query, I can get the average galon price per month just fine.
SELECT timestamp, avg(galon_price) as avg_per_month FROM 'gas_prices' SAMPLE BY 1M
timestamp
avg_per_month
2000-06-05T00:00:00.000000Z
1.6724
2000-07-05T00:00:00.000000Z
1.69275
2000-08-05T00:00:00.000000Z
1.635
...
...
Then, I get all these monthly averages, group them by year and return the maximum galon price per year by wrapping the above query in a subquery, like so:
SELECT timestamp, max(avg_per_month) as max_per_year FROM (
SELECT timestamp, avg(galon_price) as avg_per_month FROM 'gas_prices' SAMPLE BY 1M
) SAMPLE BY 12M
timestamp
max_per_year
2000-01-05T00:00:00.000000Z
1.69275
2001-01-05T00:00:00.000000Z
1.767399999999
2002-01-05T00:00:00.000000Z
1.52075
...
...
Wanted output
I want to know which month was responsible for the maximum price of a year.
Looking at the output of the above query, we see that the maximum galon price for the year 2000 was 1.69275. Which month of the year 2000 had this amount as average price? I'd like to display this month in an additional column.
For the first row, July 2000 is shown in the additional column for year 2000 because it is responsible for the highest average price in 2000. For the second row, it was May 2001 as that month had the highest average price of 2001.
timestamp
max_per_year
which_month_is_responsible
2000-01-05T00:00:00.000000Z
1.69275
2000-07-05T00:00:00.000000Z
2001-01-05T00:00:00.000000Z
1.767399999999
2001-05-05T00:00:00.000000Z
...
...
What did I try?
I tried by adding a subquery to the SELECT to have a "duplicate" of some sort for the timestamp column but that's apparently never valid in QuestDB (?), so probably the solution is by adding even more subqueries in the FROM? Or a UNION?
Who can help me out with this? The data is there in the database and it can be calculated. It's just a matter of getting it out.
I think 'wanted output' can be achieved with window functions.
Please have a look at:
CREATE TABLE electricity (ts TIMESTAMP, consumption DOUBLE) TIMESTAMP(ts);
INSERT INTO electricity
SELECT (x*1000000)::timestamp, rnd_double()
FROM long_sequence(10000000);
SELECT day, ts, max_per_day
FROM
(
SELECT timestamp_floor('d', ts) as day,
ts,
avg_in_15_min as max_per_day,
row_number() OVER (PARTITION BY timestamp_floor('d', ts) ORDER BY avg_in_15_min desc) as rn_per_day
FROM
(
SELECT ts, avg(consumption) as avg_in_15_min
FROM electricity
SAMPLE BY 15m
)
) WHERE rn_per_day = 1

How to calculated on created fields? Why the calculation is wrong?

I am working on the workforce analysis project. And I did some case when conditional calculations in Google Data Studio. However, when I successfully conducted the creation of the new field, I couldn't do the calculation again based on the fields I created.
Based on my raw data, I generated the start_headcount, new_hires, terminated, end_headcount by applying the Case When conditional calculations. However, I failed in the next step to calculate the Turnover rate and Retention rate.
The formula for Turnover rate is
terms/((start_headcount+end_headcount)/2)
for retention is
end_headcount/start_headcount
However, the result is wrong. Part of my table is as below:
Supervisor sheadcount newhire terms eheadcount turnover Retention
A 1 3 1 3 200% 0%
B 6 2 2 6 200% 500%
C 6 1 3 4 600% 300%
So the result is wrong. The turnover rate for A should be 1/((1+3)/2)=50%; For B should be 2/((6+6)/2)=33.33%.
I don't know why it is going wrong. Can anyone help?
For example, I wrote below for start_headcount for each employee
CASE
WHEN Last Hire Date<'2018-01-01' AND Termination Date>= '2018-01-01'
OR Last Hire Date<'2018-01-01' AND Termination Date IS NULL
THEN 1
ELSE 0
END
which means if an employee meets the above standard, will get 1. And then they all grouped under a supervisor. I think it might be the problem why the turnover rate in sum is wrong since it is not calculated on the grouped date but on each record and then summed up.
Most likely you are trying to do both steps within the same query and thus newly created fields like start_headcount, etc. not visible yet within the same select statement - instead you need to put first calculation as a subquery as in example below
#standardSQL
SELECT *, terms/((start_headcount+end_headcount)/2) AS turnover
FROM (
<query for your first step>
)

How to Caluculate data per year per employee

I need to find a way to calculate total salary per employee per year
I have a list of employee's data which i need to sum their total salaries per each employee per year
below is sample data
This is basic use of SQL that would be covered in any class, book, or online course. In general you should not ask these "how do you code it" questions on this site but instead ask questions about code you have already written, we are not here to write it for you we are here to help if you have problems. On the other hand it is easy:
select employee_no, year, sum(sal_amount)
from table_name_you_did_no_say
group by emplyee_no, year
You could make yourself a formula like this:
salary_per_annum = salary_per_month * 12
What you really need to do is to first categorize your staff based on the salary they earn.
If they earn allowances/bonuses, you could make a different calculations for that too and then add the both values.
If you're talking of an SQL query, for each employee, you could loop:
select sum(salary) * 12
If you're looking to calculate and group, you could have:
select employee_num, sal_year, salary from tbl_payrol group by emplyee_num, sal_amount

Getting a snapshot of records where an "event" can mean several entries on the same date

This is really frustrating me.
So, I'm making a database recording people joining and leaving our office, as well as changing roles, in order to keep track of headcount. This is succinctly recorded in the following table:
EmployeeID | RoleID | FTE | Date
FTE is the proportion of full-time hours the role is worth (i.e. 1 is full-time, 0.5 is part-time, etc). Leaving events are recorded as changing the role to 0 (Absent) and FTE to 0. The trouble is, people can have more than one role, which means that the number of hours they actually worked is a composite of all the events for that employee that occur on the same day. So if someone goes from full time on one project to splitting their time between two projects, a ChangeRole event is logged for each.
So I want to know the total headcount on a monthly basis. Essentially the query I would want is "Select all records from this table where, for each EmployeeID, the date is the maximum date below a specified date." From there I can sum the FTE to get the headcount.
Now I can get some of those things in isolation: I can do max(date), I can do criteria:<#dd/mm/yyyy##. But for some reason I can't seem to combine it all to get what I want, and I'm at a point where I've been staring at the problem so long that it doesn't make sense to me. Can anyone help me out? Thanks!
Something like this?
SELECT Events.*
FROM Events INNER JOIN (
SELECT EmployeeID, Max(Date) AS LatestDate
FROM Events
WHERE Events.Date < [Date entered]
GROUP BY EmployeeID) AS S
ON (Events.EmployeeID = S.EmployeeID) AND (Events.Date = S.LatestDate)

How do I calculate a profit for each month in MS Access?

I'm quite new to access and I am currently in the process of making a database for my company.
I have a 'Jobs' table with these fields in:
Job No.
Year Initiated
Month Initiated
Company ID
Job Description
Amount Quoted
Amount to Invoice
Invoice Number
Completed By
Cost
Profit
What I want to know Is what is the best way/ how do I calculate either in a form or query the overall profit for each month?
Please help, the database is really coming along, apart from this is well entruely stuck on.
You want to find all rows matching a specific year / month, and add together all the profit entries for that month to get a total?
If so, try this :
select sum(profit) from Jobs where year = 2013 and month = 02
Or, if you want to retrieve this information for all months in one go, try this :
select year, month, sum(profit) from Jobs group by year, month