How to Calculate Working Hours including Minutes? - sql

I have a query that fetches employee's name, date, working hours, wage and calculate salary based on working hours * wage.
The minutes in working hours that is being calculated are discarded. I only get the value in full hour. Snapshot example:
My main concern is on workingHours and wageAmount
workingHours is displayed as 5. Here is the time sheet snapshot:
As you see shift starts at 10:30 AM and ends at 4:00 PM (excluding lunch time), so the actual total hours is 4 and a half not 5.
Here is the query snippet that calculates the hours:
DATEDIFF(HOUR, shiftStart.timeEntered, shiftEnd.timeEntered) - DATEDIFF(HOUR, lunchStart.timeEntered, lunchEnd.timeEntered) AS workingHours,
MY QUESTION IS:
1. How can i calculate working hours accurately with minutes included (discard seconds)?
Since i will be counting the minutes, i will have to calculate the wage per minute so i will have to put the following code that calculates wage per minute:
ROUND((((DATEDIFF(HOUR, shiftStart.timeEntered, shiftEnd.timeEntered) - DATEDIFF(HOUR, lunchStart.timeEntered, lunchEnd.timeEntered)) * 60) * (cast(((w.wageAmount/60)-((w.wageAmount/60)%.001)) as decimal (18,3)))), 0) AS "SalaryPerMin",

Use DATEDIFF(minute, shiftStart.timeEntered, shiftEnd.timeEntered) * 1.0 / 60 instead, to give you the hour as a decimal.

Time card stuff is very business rule intensive. I would consider your architecture before putting all the rules in sp's.

This will return the Hours & Minutes:
CAST(DATEDIFF(MINUTE, StartTime, EndTime) AS DECIMAL)/60

Related

Is there a way to take the output of a (HH24:MI:SS - HH24:MI:SS) and convert it to only minutes in oracle sql?

So i am putting the sql code in that i have shown below and my output that i get from the ProcessEnd minus ProcessStart is the duration time which comes out as "0 0:0:8.135". However, i need it to only show in terms of minutes, i don't want the hours or seconds, just the minutes the process runs.
TO_CHAR(rh.PROCESSSTART,'DD-MM-YYYY HH24:MI:SS') AS "PROCESSSTART",
TO_CHAR(rh.PROCESSEND,'DD-MM-YYYY HH24:MI:SS') AS "PROCESSEND",
(rh.PROCESSEND - rh.PROCESSSTART) AS "DURATION",
"0 0:0:8.135"
It looks that PROCESSEND and PROCESSSTART are DATEs.
If so, subtracting them results in number of days.
In order to get number of minutes, you'll have to multiply number of days by
24, as there are 24 hours in a day
60, as there are 60 minutes in an hour
so the final result would be
(rh.processend - rh.processstart) * 24 * 60 as number_of_minutes

how to write a sql to calculate working hours minus rest time

I have a table of rest time in work shift
Begin end
12:00 12:30
17:30 18:30
Now I want to write a SQL to calculate actual working hours given the start and end time. For example if start at 9:00 and end at 15:00, the actual hours is 6-rest time=5.5 hours and if start at 9:00 and end at 20:00 the actual hours is 10 hours. How to write a procedure to check it in SQL server? Thx.
There are no schema details to work with here, which means the following SQL is generic and will have to be altered to fit your db.
SELECT
(datediff(minute, shiftStartTime, shiftEndTime)
- datediff(minute,breakStartTime,breakEndTime)) / 60.0
FROM yourTable
Notes:
If they can have multiple breaks, you need to sum up all the break times in minutes before deducting it from the shift period.
the calculation is specifically in minutes because the datediff counts the number of boundaries passed, so the date diff in hours between 11:59 and 12:01 is 1, even though the break is 2 minutes, you would count that as 1 hour if you count hours using the function.
If you can provide more schema details, we would be able to craft a more complete statement.
you can try below way using DATEDIFF
select *, CONVERT(time(7),DATEADD(s, DATEDIFF(s,S,E),'00:00:00')) from QQ
http://sqlfiddle.com/#!18/01213d/1
for your case column name will be
select *, CONVERT(time(7),DATEADD(s, DATEDIFF(s,Begin,end),'00:00:00')) from yourtable

sql statement - would like to subtract 1 date from another and get the days hours and mins inbetween

I would like to subtract 1 date from another and get the days hours and mins in-between.
I know there is a DateDiff function, however it does not work with all 3 time values; days hours and mins. I would like this doable in an SQL statement. Currently I have the following.
SELECT id, pickupdateandtime, GETDATE() AS CurrentTime,
(DATEDIFF(day,GETDATE(),pickupdateandtime)) AS Days,
(DATEDIFF(hour,GETDATE(),pickupdateandtime)) AS Hours,
(DATEDIFF(minute,GETDATE(),pickupdateandtime)) AS Mins FROM orders
And it shows up like this:
If we can stick it all in 1 column that's fine too.
I agree with #AndyMcLaughlin about the use of the mod operator % here. It's very handy for this sort of thing. However, I have a general distrust of DATEDIFF. That function does not count the whole number of years (say) between two dates, but the number of year boundaries between them.
So DATEDIFF "thinks" the difference in years between 01-Jan-2000 and 01-Jan-2001 is the same as that between 31-Dec-2000 and 01-Jan-2001.
This is why #Michael saw a need to subtract 1 from #AndyMcLaughlin's results. Unfortunately, that doesn't always work, it will depend on the individual case.
As a rule, DATEDIFF works well when it's used against the smallest interval you are interested in. So if you are interested in years and simply want to separate one calendar year from another, it'll serve you well.
I think the smallest interval we are interested in here is minutes. So we can use DATEDIFF for that, but have to work upwards from there to hours and days:
select
mf.id,
mf.pickupdateandtime,
mf.CurrentTime,
--The divisions in the following lines simply
--truncate since all the numbers are integers
--but that works in our favour here
(mf.MinutesFull/(60*24)) as Days,
(mf.MinutesFull/60) % 24 as Hours,
mf.MinutesFull % 60 as Minutes
from
(
select
id,
pickupdateandtime,
getdate() as CurrentTime,
datediff(minute, getdate(), pickupdateandtime) as MinutesFull
from #orders
) mf
You need to use the mod operator % to remove whole days from hours and whole hours from minutes.
So you can do something like:
SELECT
id,
pickupdateandtime,
GETDATE() AS CurrentTime,
(DATEDIFF(day,GETDATE(),pickupdateandtime)) AS Days,
(DATEDIFF(hour,GETDATE(),pickupdateandtime) % 24) AS Hours,
(DATEDIFF(minute,GETDATE(),pickupdateandtime) % 60) AS Mins FROM orders

Optimization: How to get TimeId from time for each minute in a week?

I am creating a table which will have 2 columns:
Day_time (time from 1978-01-01 00:00:00 Sunday, till 1978-01-07 23:59:00.0 Saturday, Granularity: Minute)
Time_id (a unique id for each minute), to be populated
I have column one populated. I want to populate column two.
How I am doing it right now:
EXTRACT(dayofweek FROM day_time) * 10000 + DATEDIFF('minutes', TRUNC(day_time), day_time)
I basically want a function where I pass any date and it tells me where I am in a week. So, I need a function, just like the function above. Just more optimized, where I give a date and get a unique ID. The unique ID should repeat weekly.
Example: ID for Jan 1, 2015 00:00:00 will be same as Jan 8, 2015 00:00:00.
Why 1978-01-01? cuz it starts from a Sunday.
Why 10,000? cuz the number of minutes in a day are in four digits.
You can do it all in one fell swoop, without needing to extract the date separately:
SELECT DATEDIFF('minutes', date_trunc('week',day_time), day_time) which I'd expect to be marginally faster.
Another approach that I'd expect to be significantly faster would be converting the timestamp to epoch, dividing by 60 to get minutes from epoch and then taking the value modulus of 10,080 (for 60 * 24 * 7 minutes in a week).
SELECT (extract(epoch from day_time) / 60) % 10080
If you don't care about the size of the weekly index, you could also do:
SELECT (extract(epoch from day_time)) % 604800 and skip the division step altogether, which should make it faster still.

Updating dates with random time

I have a datetime column, all of them at 12:00 am. Is there a way to update them with random hours, minutes to nearest 1/2 hour while keeping the same date(day) value?
Update Activities set ActivityDate = ....
Here's one option using dateadd:
update Activities
set ActivityDate = DateAdd(minute,
30 * (abs(checksum(NewId())) % 47), ActivityDate);
SQL Fiddle Demo
And here's a good post about generating random numbers. Using that, multiple by 30 minutes to get to the nearest half hour.
Note, this uses % 47 since there are 1440 minutes in a day -- that divides into 48 potential half hour segments in that same day.