Hei guys, I'm trying to help my friend to design database tables. It is for a system tracking workers' working hours in a factory by reading card info from certain card readers. Each time a worker log his in/out information, there would be an record saved.
My problem is, how can I calculate each worker's working time (in minutes), each workday? A worker may work from 8:00AM~20:00PM, or 20:00PM~8:00AM.
Anyone can help me?
Thanks!
You guys did give me a lot of help. The previous design is a table with in-record or out-record. It was hard for me to locate which ones belong to the same work-time-span. I now use another table with records both have the in-time and out-time in the same record. Insert to save in-time, update to save out-time, which makes it easy to calculate the total minutes 开发者_StackOverflow社区between in-time and out-time.
SELECT datediff(hh,'2011-08-30 04:47','2011-08-30 05:48') as [Hour(s) Worked]
Hour(s) Worked
--------------
1
a simple example with 2 tables
[TblUsers]
User_id PK
FirstName
LastName
[TblSchedule]
Schedule_id PK
User_id FK
Date_From
Date_To
to get a daily work grid with times, you can write something like:
SELECT
u.FirstName + ' ' + u.LastName as [username],
CAST(FLOOR(CAST(@datetime as float)) as datetime) as [date],
DATEDIFF(minute, s.Date_To, s.Date_From) as [workMinutes]
FROM
[TblSchedule] s, [TblUsers] u
WHERE
s.user_id = u.user_id
GROUP BY
u.FirstName + ' ' + u.LastName,
CAST(FLOOR(CAST(@datetime as float)) as datetime)
ORDER BY
s.Date_From;
Just calculate the Minutes between each IN-Record
and the following OUT-Record
from this worker. If you want it for a whole day then fetch the relevant records and sum up the relevant differences.
The more complex thing here is when some worker forget about stamping. Your program have to be prepared for such cases.
Also be aware of things like daylight saving time. Time-Calcs can be very complicated.
I think I would do calculation on application level and not in SQL in this case.
DATEDIFF
can give you some strange results.
For example take this two DATETIME2
(I presume you have SQL Server 2008) values that have a difference of 5 minutes:
SELECT DATEDIFF(hh,'2011-01-01 04:59:00','2011-01-01 05:04:00')
Results
-----------
1
The result is somehow strange: 1 hour. Strange, because the difference in minutes is 5 minutes but the difference in hours is 1 hour and we know that 1 hour = 60 minutse. Please read this article to see the explanations.
Solutions:
1) Instead of DATEDIFF(hh,...)
use DATEDIFF(mi,...)
Ex:
SELECT DATEDIFF(mi,'2011-01-01 07:55:00','2011-01-01 16:02:00') [Minutes]
,DATEDIFF(mi,'2011-01-01 07:55:00','2011-01-01 16:02:00')/60 [Hours]
--8 hours
,DATEDIFF(mi,'2011-01-01 07:55:00','2011-01-01 16:02:00')%60 [Additional minute]
--7 minute
But:
SELECT DATEDIFF(mi,'2011-01-01 08:00:59','2011-01-01 16:00:05') [Minutes]
--480
,DATEDIFF(ss,'2011-01-01 08:00:59','2011-01-01 16:00:05')/60 [Seconds/60]
--479
2) Instead of using DATEDIFF
function (with DATETIME[2][OFFSET]
data types) use DATETIME
values with the - operator:
DECLARE @Test TABLE
(
TestId INT IDENTITY(1,1) PRIMARY KEY
,[Enter] DATETIME NOT NULL
,[Exit] DATETIME NOT NULL
);
INSERT @Test
VALUES ('2011-01-01 07:55:00','2011-01-01 16:02:02')
,('2011-01-01 08:00:59','2011-01-01 16:00:05');
SELECT *
,t.[Exit] - t.[Enter] AS MyDateDiff
,DATEPART(hh,t.[Exit] - t.[Enter]) [Hours]
,DATEPART(mi,t.[Exit] - t.[Enter]) [Additional minutes]
,DATEPART(ss,t.[Exit] - t.[Enter]) [Additional seconds]
FROM @Test t
Results:
TestId Enter Exit MyDateDiff Hours Additional minute Additional seconds
----------- ----------------------- ----------------------- ----------------------- ----------- ----------------- ------------------
1 2011-01-01 07:55:00.000 2011-01-01 16:02:02.000 1900-01-01 08:07:02.000 8 7 2
2 2011-01-01 08:00:59.000 2011-01-01 16:00:05.000 1900-01-01 07:59:06.000 7 59 6
精彩评论