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.
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 startsClockIn Time --------------- ClockOut Time2008-02-20 10:05:13.000, 2008-02-20 18:14:50.000ClockIn Time --------------- ClockOut Time2008-02-21 09:54:25.000, 2008-02-21 12:25:00.0002008-02-21 13:00:05.000, 2008-02-21 15:00:00.0002008-02-21 15:28:05.000, 2008-02-21 17:00:00.000then 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 KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/ |
 |
|
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 |
 |
|
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 KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/ |
 |
|
mrtanvirali
Starting Member
41 Posts |
Posted - 2008-03-06 : 02:13:27
|
I've checked and tried but failed to calculate |
 |
|
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 KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/ |
 |
|
mrtanvirali
Starting Member
41 Posts |
Posted - 2008-03-06 : 03:30:53
|
ClockIn Time -------------- ClockOut Time02/20/2008 11:26:11 AM -- 02/20/2008 7:00:00 PM02/21/2008 9:54:25 AM -- 02/21/2008 2:25:00 PM02/21/2008 2:48:05 PM -- 02/21/2008 5:00:00 PM02/22/2008 12:55:19 PM -- 02/22/2008 6:00:00 PM02/25/2008 10:05:13 AM -- 02/25/2008 3:14:50 PM02/25/2008 3:44:52 PM -- 02/25/2008 6:05:07 PM02/25/2008 6:15:08 PM -- 02/25/2008 6:20:31 PM02/25/2008 6:30:33 PM -- 02/25/2008 7:00:00 PM02/26/2008 11:33:59 AM -- 02/26/2008 5:50:00 PM02/27/2008 10:24:16 AM -- 02/27/2008 2:34:44 PM02/27/2008 2:34:47 PM -- 02/27/2008 5:15:00 PM02/28/2008 9:46:16 AM -- 02/28/2008 6:20:00 PM02/29/2008 10:01:03 AM -- 02/29/2008 2:15:32 PM02/29/2008 4:17:16 PM -- 02/29/2008 6:35:11 PMSelect Datediff(mi,'02/25/2008 3:14:50','02/25/2008 3:44:52')the above is hard coded, i just want through querySELECT In_Time, Out_Time, UserID, Datediff(mi,Out_Time,In_Time)FROM tblwhere (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 dayits just show me the wrong calculated data |
 |
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-03-06 : 06:44:00
|
what was result you got? |
 |
|
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 |
 |
|
mrtanvirali
Starting Member
41 Posts |
Posted - 2008-03-06 : 23:50:55
|
yes Jeff, that's what i want to do |
 |
|
mrtanvirali
Starting Member
41 Posts |
Posted - 2008-03-07 : 00:06:44
|
it shows wrong result like clockIn Time ----------------- ClockOut Time ------------ User Id -- Break Time2008-02-21 09:54:25.000 ---- 2008-02-21 14:25:00.000 ---- 36 -- -2712008-02-21 14:48:05.000 ---- 2008-02-21 17:00:00.000 ---- 36 -- -1322008-02-22 12:55:19.000 ---- 2008-02-22 18:00:00.000 ---- 36 -- -3052008-02-25 10:05:13.000 ---- 2008-02-25 15:14:50.000 ---- 36 -- -3092008-02-25 15:44:52.000 ---- 2008-02-25 18:05:07.000 ---- 36 -- -1412008-02-25 18:15:08.000 ---- 2008-02-25 18:20:31.000 ---- 36 -- -52008-02-25 18:30:33.000 ---- 2008-02-25 19:00:00.000 ---- 36 -- -302008-02-26 11:33:59.000 ---- 2008-02-26 17:50:00.000 ---- 36 -- -377it 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 |
 |
|
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 --271SELECT '2008-02-21 14:48:05.000','2008-02-21 17:00:00.000',36 UNION ALL --132SELECT '2008-02-22 12:55:19.000','2008-02-22 18:00:00.000',36 UNION ALL --305SELECT '2008-02-25 10:05:13.000','2008-02-25 15:14:50.000',36 UNION ALL --309SELECT '2008-02-25 15:44:52.000','2008-02-25 18:05:07.000',36 UNION ALL --141SELECT '2008-02-25 18:15:08.000','2008-02-25 18:20:31.000',36 UNION ALL --5SELECT '2008-02-25 18:30:33.000','2008-02-25 19:00:00.000', 36 UNION ALL --30SELECT '2008-02-26 11:33:59.000','2008-02-26 17:50:00.000', 36 --377SELECT 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) oon i.InRow = o.Outrow and datediff(d,0,i.clockin) = datediff(d,0,o.clockout)and o.clockin is not nullDrop table #foo/*Startime TimeOut End Break Break2008-02-21 09:54:25.000 2008-02-21 14:25:00.000 2008-02-21 14:48:05.000 232008-02-25 10:05:13.000 2008-02-25 15:14:50.000 2008-02-25 15:44:52.000 302008-02-25 15:44:52.000 2008-02-25 18:05:07.000 2008-02-25 18:15:08.000 102008-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. |
 |
|
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 |
 |
|
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. |
 |
|
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.ClockInDROP 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 |
 |
|
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. |
 |
|
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. |
 |
|
mrtanvirali
Starting Member
41 Posts |
Posted - 2008-03-12 : 09:01:57
|
ya its working fine, once again thanks! |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2008-03-12 : 09:34:31
|
If you only want aggregated times per day, try thisDECLARE @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 ALLSELECT '2008-02-21 14:48:05', '2008-02-21 17:00:00', 36 UNION ALLSELECT '2008-02-22 12:55:19', '2008-02-22 18:00:00', 36 UNION ALLSELECT '2008-02-25 10:05:13', '2008-02-25 15:14:50', 36 UNION ALLSELECT '2008-02-25 15:44:52', '2008-02-25 18:05:07', 36 UNION ALLSELECT '2008-02-25 18:15:08', '2008-02-25 18:20:31', 36 UNION ALLSELECT '2008-02-25 18:30:33', '2008-02-25 19:00:00', 36 UNION ALLSELECT '2008-02-26 11:33:59', '2008-02-26 17:50:00', 36SELECT 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 BreakMinutesFROM ( 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" |
 |
|
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" |
 |
|
mrtanvirali
Starting Member
41 Posts |
Posted - 2008-03-18 : 03:44:14
|
Very nice attempt Peso |
 |
|
Next Page
|
|
|
|
|