Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 How to calculate Break Time

Author  Topic 

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-06 : 01:44:50
I've checked this forum and found very suitable things here so i am posting here, actually I am working on Time Trax application that manage the working and break times of employees, the folowing are the dummy clockin and clockout times, when employee clocked in his / her working time starts and when he / she clocked out then the break time starts

ClockIn Time --------------- ClockOut Time
2008-02-20 10:05:13.000, 2008-02-20 18:14:50.000

ClockIn Time --------------- ClockOut Time
2008-02-21 09:54:25.000, 2008-02-21 12:25:00.000
2008-02-21 13:00:05.000, 2008-02-21 15:00:00.000
2008-02-21 15:28:05.000, 2008-02-21 17:00:00.000

then how would I calculate the break time between two / three clockedIn and clockedOut time within the same day

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-03-06 : 01:50:11
You can use the DATEDIFF function to find the difference between two datetime columns.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-06 : 01:54:04
tkizer, can you give me any example of it that calculate only the total break time
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-03-06 : 02:03:06
Check SQL Server Books Online for how to use the function.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-06 : 02:13:27
I've checked and tried but failed to calculate
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-03-06 : 02:14:22
Show us what you tried, any errors it gave, or why it was wrong.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-06 : 03:30:53

ClockIn Time -------------- ClockOut Time
02/20/2008 11:26:11 AM -- 02/20/2008 7:00:00 PM
02/21/2008 9:54:25 AM -- 02/21/2008 2:25:00 PM
02/21/2008 2:48:05 PM -- 02/21/2008 5:00:00 PM
02/22/2008 12:55:19 PM -- 02/22/2008 6:00:00 PM
02/25/2008 10:05:13 AM -- 02/25/2008 3:14:50 PM
02/25/2008 3:44:52 PM -- 02/25/2008 6:05:07 PM
02/25/2008 6:15:08 PM -- 02/25/2008 6:20:31 PM
02/25/2008 6:30:33 PM -- 02/25/2008 7:00:00 PM
02/26/2008 11:33:59 AM -- 02/26/2008 5:50:00 PM
02/27/2008 10:24:16 AM -- 02/27/2008 2:34:44 PM
02/27/2008 2:34:47 PM -- 02/27/2008 5:15:00 PM
02/28/2008 9:46:16 AM -- 02/28/2008 6:20:00 PM
02/29/2008 10:01:03 AM -- 02/29/2008 2:15:32 PM
02/29/2008 4:17:16 PM -- 02/29/2008 6:35:11 PM

Select Datediff(mi,'02/25/2008 3:14:50','02/25/2008 3:44:52')

the above is hard coded, i just want through query

SELECT In_Time, Out_Time, UserID, Datediff(mi,Out_Time,In_Time)
FROM tbl
where (CAST(CAST(In_Time AS varchar(11)) AS datetime)>= CAST(CAST('2008-02-21' AS varchar(11)) AS datetime)) AND (CAST(CAST(In_Time AS varchar(11)) AS datetime) <= CAST(CAST('2008-02-26' AS varchar(11)) AS datetime))


with multiple clockedIn and ClockedOut per day
its just show me the wrong calculated data
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-03-06 : 06:44:00
what was result you got?
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2008-03-06 : 10:22:41
Ummmm... the OP wants to calculate the BREAK time... in other words, the Delta-T between the clock OUT time and the next clock IN time on the same day... op didn't quite say it right in the original post...

--Jeff Moden
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-06 : 23:50:55
yes Jeff, that's what i want to do
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-07 : 00:06:44
it shows wrong result like
clockIn Time ----------------- ClockOut Time ------------ User Id -- Break Time
2008-02-21 09:54:25.000 ---- 2008-02-21 14:25:00.000 ---- 36 -- -271
2008-02-21 14:48:05.000 ---- 2008-02-21 17:00:00.000 ---- 36 -- -132
2008-02-22 12:55:19.000 ---- 2008-02-22 18:00:00.000 ---- 36 -- -305
2008-02-25 10:05:13.000 ---- 2008-02-25 15:14:50.000 ---- 36 -- -309
2008-02-25 15:44:52.000 ---- 2008-02-25 18:05:07.000 ---- 36 -- -141
2008-02-25 18:15:08.000 ---- 2008-02-25 18:20:31.000 ---- 36 -- -5
2008-02-25 18:30:33.000 ---- 2008-02-25 19:00:00.000 ---- 36 -- -30
2008-02-26 11:33:59.000 ---- 2008-02-26 17:50:00.000 ---- 36 -- -377

it is showing difference between current ClockIn and ClockOut Times But, I want to take the difference Between the last clockout time and the next clockin time on the same day
Go to Top of Page

dataguru1971
Master Smack Fu Yak Hacker

1464 Posts

Posted - 2008-03-07 : 01:20:40
[code]
Create Table #foo (clockin datetime not null, clockout datetime not null,userid int not null)

Insert Into #foo (clockin, clockout,userid)

SELECT '2008-02-21 09:54:25.000','2008-02-21 14:25:00.000',36 UNION ALL --271
SELECT '2008-02-21 14:48:05.000','2008-02-21 17:00:00.000',36 UNION ALL --132
SELECT '2008-02-22 12:55:19.000','2008-02-22 18:00:00.000',36 UNION ALL --305
SELECT '2008-02-25 10:05:13.000','2008-02-25 15:14:50.000',36 UNION ALL --309
SELECT '2008-02-25 15:44:52.000','2008-02-25 18:05:07.000',36 UNION ALL --141
SELECT '2008-02-25 18:15:08.000','2008-02-25 18:20:31.000',36 UNION ALL --5
SELECT '2008-02-25 18:30:33.000','2008-02-25 19:00:00.000', 36 UNION ALL --30
SELECT '2008-02-26 11:33:59.000','2008-02-26 17:50:00.000', 36 --377

SELECT i.clockin as StartTime,i.Clockout as StartBreak,o.clockin as EndBreak, datediff(mi,i.clockout,o.clockin)
From (Select ROW_NUMBER() OVER (order by Clockin) as InRow,Clockin,Clockout
FROM #foo) i
inner join
(Select ROW_NUMBER() OVER (order by Clockin)-1 as OutRow, Clockin,Clockout
FROM #foo) o
on i.InRow = o.Outrow and datediff(d,0,i.clockin) = datediff(d,0,o.clockout)
and o.clockin is not null

Drop table #foo
/*
Startime TimeOut End Break Break
2008-02-21 09:54:25.000 2008-02-21 14:25:00.000 2008-02-21 14:48:05.000 23
2008-02-25 10:05:13.000 2008-02-25 15:14:50.000 2008-02-25 15:44:52.000 30
2008-02-25 15:44:52.000 2008-02-25 18:05:07.000 2008-02-25 18:15:08.000 10
2008-02-25 18:15:08.000 2008-02-25 18:20:31.000 2008-02-25 18:30:33.000 10

[/code]


It may be horrendous by some of the standards here, but I figured out something that works. This is for 2005 though....not sure how the best way in 2000 would be with Jeff's favority triangular join (which I think I did above anyway)





Poor planning on your part does not constitute an emergency on my part.

Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2008-03-07 : 10:54:48
No... you did good... you avoided the triangular join (which you should). In fact, you used the a classic method of solving this problem for 2k5. Classic method in 2k would have used a temp table with an IDENTITY column to make the row numbers.

Only thing that might have been better is to realize that you can use a CTE more than once just like a temp table... no need for two separate derived tables. I'll be back in a couple minutes...

--Jeff Moden
Go to Top of Page

dataguru1971
Master Smack Fu Yak Hacker

1464 Posts

Posted - 2008-03-07 : 11:01:06
Thanks Jeff.

I am stuck in 2000 at work, so i don't get many opportunities to practice on 2005, which I have at home. A CTE would allow for the use of identity row number.(Derived tables don't allow them..right?)...

Since the OP had 2000, I kept trying to play around with it, but it seems it would require two temp tables and identity columns, joined in a fashion like I did above.

I look forward to seeing the CTE option..so I can figure out how that works.



Poor planning on your part does not constitute an emergency on my part.

Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2008-03-07 : 19:33:50
Sorry for the delay... working for a living got in the way (heh... I'm a poet and don't know it...)

Ok... here's the SQL Server 2000 way to do it without using a triangular join...
--=============================================================================
-- Create and populate a table of sample data.
-- THIS IS NOT PART OF THE SOLUTION
--=============================================================================
CREATE TABLE #yourtable
(
ClockIn DATETIME,
ClockOut DATETIME,
UserID INT
)
INSERT INTO #yourtable
(ClockIn, ClockOut, UserID)
SELECT '2008-02-21 09:54:25.000','2008-02-21 14:25:00.000',36 UNION ALL
SELECT '2008-02-21 14:48:05.000','2008-02-21 17:00:00.000',36 UNION ALL
SELECT '2008-02-22 12:55:19.000','2008-02-22 18:00:00.000',36 UNION ALL
SELECT '2008-02-25 10:05:13.000','2008-02-25 15:14:50.000',36 UNION ALL
SELECT '2008-02-25 15:44:52.000','2008-02-25 18:05:07.000',36 UNION ALL
SELECT '2008-02-25 18:15:08.000','2008-02-25 18:20:31.000',36 UNION ALL
SELECT '2008-02-25 18:30:33.000','2008-02-25 19:00:00.000',36 UNION ALL
SELECT '2008-02-26 11:33:59.000','2008-02-26 17:50:00.000',36

--=============================================================================
-- Since SQL Server 2000 doesn't have a ROW_NUMBER() function, we have to
-- move the data to a temp table that has an IDENTITY column on it to make
-- the necessary row number for an ordered set. Since the IDENTITY
-- column will be used to reflect the order of data, we must create the
-- temp table first and then populate it instead of using SELECT/INTO.
-- This is pretty fast and certainly faster than doing a bunch of MIN
-- comparisons using correlated subqueries.
--=============================================================================
--===== This creates an empty temp table using SELECT/INTO... (cheater)
SELECT IDENTITY (INT,1,1) AS RowNum,
ClockIn,
ClockOut,
UserID
INTO #MyWork
FROM #yourtable
WHERE 1 = 0 --This forces zero rows to be transferred.

--===== Use the same query with an order by to actually move the ordered data
INSERT INTO #MyWork
(ClockIn, ClockOut, UserID)
SELECT ClockIn,
ClockOut,
UserID
FROM #yourtable
ORDER BY UserID, ClockIn

--===== Calculate and display break times that are <= 1 hour
SELECT t1.UserID,
t2.ClockOut,
t1.ClockIn,
DATEDIFF(mi,0,t1.ClockIn-t2.ClockOut) AS BreakMinutes
FROM #MyWork t1,
#MyWork t2
WHERE t1.RowNum=t2.RowNum+1
AND t1.UserID=t2.UserID
AND DATEDIFF(mi,0,t1.ClockIn-t2.ClockOut) <=60 --1 Hour
ORDER BY t1.UserID,t1.ClockIn

DROP TABLE #yourtable,#MyWork


... and here's how I'd do it with a CTE in 2005...

--=============================================================================
-- Create and populate a table of sample data.
-- THIS IS NOT PART OF THE SOLUTION
--=============================================================================
CREATE TABLE #yourtable
(
ClockIn DATETIME,
ClockOut DATETIME,
UserID INT
)
INSERT INTO #yourtable
(ClockIn, ClockOut, UserID)
SELECT '2008-02-21 09:54:25.000','2008-02-21 14:25:00.000',36 UNION ALL
SELECT '2008-02-21 14:48:05.000','2008-02-21 17:00:00.000',36 UNION ALL
SELECT '2008-02-22 12:55:19.000','2008-02-22 18:00:00.000',36 UNION ALL
SELECT '2008-02-25 10:05:13.000','2008-02-25 15:14:50.000',36 UNION ALL
SELECT '2008-02-25 15:44:52.000','2008-02-25 18:05:07.000',36 UNION ALL
SELECT '2008-02-25 18:15:08.000','2008-02-25 18:20:31.000',36 UNION ALL
SELECT '2008-02-25 18:30:33.000','2008-02-25 19:00:00.000',36 UNION ALL
SELECT '2008-02-26 11:33:59.000','2008-02-26 17:50:00.000',36

--=============================================================================
-- Since SQL Server 2005 does have a ROW_NUMBER() function, don't have to
-- move data into a temp table to get the equivalent of an IDENTITY column.
-- And, since a CTE can be used more than once in the same query, we only
-- need 1 CTE. All of it makes for some very short, easy to read, high
-- speed code.
--=============================================================================
;WITH cteMyWork AS
(
SELECT ROW_NUMBER() OVER (ORDER BY UserID,ClockIn) AS RowNum,
ClockIn,
ClockOut,
UserID
FROM #yourtable
)
SELECT t1.UserID,
t2.ClockOut,
t1.ClockIn,
DATEDIFF(mi,0,t1.ClockIn-t2.ClockOut) AS BreakMinutes
FROM cteMyWork t1,
cteMyWork t2
WHERE t1.RowNum=t2.RowNum+1
AND t1.UserID=t2.UserID
AND DATEDIFF(mi,0,t1.ClockIn-t2.ClockOut) <=60 --1 Hour

DROP TABLE #yourtable




--Jeff Moden
Go to Top of Page

dataguru1971
Master Smack Fu Yak Hacker

1464 Posts

Posted - 2008-03-07 : 20:18:55
Thanks for posting that Jeff.

The only way I could come up with was using the temp table with identity...just as you did, but as in the post from the other day..i didn't want have another RBAR moment....







Poor planning on your part does not constitute an emergency on my part.

Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-10 : 01:44:54
Thanx all of you specially Jeff Moden and dataguru1971 to work out on the scenario, I'll reply soon after checking / implementing.
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-12 : 09:01:57
ya its working fine, once again thanks!
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-03-12 : 09:34:31
If you only want aggregated times per day, try this
DECLARE	@Sample TABLE
(
ClockIn DATETIME,
ClockOut DATETIME,
UserID INT
)

INSERT @Sample
(
ClockIn,
ClockOut,
UserID
)
SELECT '2008-02-21 09:54:25', '2008-02-21 14:25:00', 36 UNION ALL
SELECT '2008-02-21 14:48:05', '2008-02-21 17:00:00', 36 UNION ALL
SELECT '2008-02-22 12:55:19', '2008-02-22 18:00:00', 36 UNION ALL
SELECT '2008-02-25 10:05:13', '2008-02-25 15:14:50', 36 UNION ALL
SELECT '2008-02-25 15:44:52', '2008-02-25 18:05:07', 36 UNION ALL
SELECT '2008-02-25 18:15:08', '2008-02-25 18:20:31', 36 UNION ALL
SELECT '2008-02-25 18:30:33', '2008-02-25 19:00:00', 36 UNION ALL
SELECT '2008-02-26 11:33:59', '2008-02-26 17:50:00', 36

SELECT d.UserID,
DATEADD(DAY, DATEDIFF(DAY, '19000101', d.minTime), '19000101') AS theDay,
d.theWork / 3600.0 AS WorkHours,
(DATEDIFF(SECOND, d.minTime, d.maxTime) - d.theWork) / 60.0 AS BreakMinutes
FROM (
SELECT UserID,
MIN(ClockIn) AS minTime,
MAX(ClockOut) AS maxTime,
SUM(DATEDIFF(SECOND, ClockIn, ClockOut)) AS theWork
FROM @Sample
GROUP BY UserID,
DATEDIFF(DAY, '19000101', ClockIn)
) AS d



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-03-12 : 09:38:41
Or this maybe?
SELECT		d.UserID,
DATEADD(DAY, DATEDIFF(DAY, '19000101', d.minTime), '19000101') AS theDay,
CONVERT(CHAR(8), DATEADD(SECOND, d.theWork, '19000101'), 108) AS Work,
CONVERT(CHAR(8), DATEADD(SECOND, DATEDIFF(SECOND, d.minTime, d.maxTime) - d.theWork, '19000101'), 108) AS [Break]
FROM (
SELECT UserID,
MIN(ClockIn) AS minTime,
MAX(ClockOut) AS maxTime,
SUM(DATEDIFF(SECOND, ClockIn, ClockOut)) AS theWork
FROM @Sample
GROUP BY UserID,
DATEDIFF(DAY, '19000101', ClockIn)
) AS d



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

mrtanvirali
Starting Member

41 Posts

Posted - 2008-03-18 : 03:44:14
Very nice attempt Peso
Go to Top of Page
    Next Page

- Advertisement -