Often you may come across a situation to calculate time values which are stored as numbers. There is a seperate TIME datatype to store time values starting from SQL Server 2008. But you might find that in earlier versions time values might be stored in DATETIME,Integer, Decimal, or other numeric datatypes depends on the format. Also if you import data from different system, you may need to use appropriate datatype to store time values.
Ex. The time value 02:30 AM has the following possibilities of being stored effectively based on the datatype
DATEIME : 19000101 02:30:00 (By default we can append with base date)
INTEGER : 150 (Time is converted to minutes so 2:30 hours is 150 minutes)
DECIMAL : 2.30
VARCHAR : 02:30 AM
There was a question in SQL Server forum about calculating time values which were stored in float datatype. Consider the following set of data
CREATE table #t (empid char(4), work_date datetime, working_hours float, ot_hours float, break_hours float)
INSERT INTO #t (empid, work_date, working_hours, ot_hours, break_hours)
select 'E001', '20120212', 1.3, 3.4, 0 union all
select 'E001', '20120212', 2, 1.5, 0 union all
select 'E001', '20120213', 5.0, 2.2, 0.5 union all
select 'E002', '20120213', 4.45, 0, 1.35 union all
select 'E001', '20120214', 6.1, 2.0, 1.00 union all
select 'E002', '20120214', 1.3, 3.4, 0 union all
select 'E001', '20120215', 6.2, 0, 0 union all
select 'E002', '20120215', 8.0, 0, 0 union all
select 'E002', '20120215', 1.5, 0, 4.5 union all
select 'E003', '20120215', 2.0, 1.0, 3.4
The original poster was looking for a way to produce the result in such a way that for each date if the total of three columns working_hours, ot_hours and break_hours is greater than or equal to 8 hours flag it to 1 otherwsie flag it to 0. The hours are stored in HH.MM format ie 2.3 means 2 hours and 30 minutes, 4.1 means 4 hours and 10 minutes, etc and there can't be values like 5.7,3.88,etc which are meaningless. Also addition of 2.3, 4.1 and 2.45 should be calculated as 9 hours and 25 minutes.
There can be many methods to calculate the time values that involve datatype convertions, extracting precision, scale and do calculations, etc.
Here is my method. Just do a SUM because of FLOAT datatype and when a value becomes >=7.6, it reaches 8 hours.
select
empid,
work_date ,
case when sum(working_hours+ot_hours+break_hours)>=7.6 then 1 else 0 end as status
from
#t
group by
empid,work_date
Which produces the following result
empid work_date status
----- ----------------------- -----------
E001 2012-02-12 00:00:00.000 1
E001 2012-02-13 00:00:00.000 1
E002 2012-02-13 00:00:00.000 0
E001 2012-02-14 00:00:00.000 1
E002 2012-02-14 00:00:00.000 0
E001 2012-02-15 00:00:00.000 0
E002 2012-02-15 00:00:00.000 1
E003 2012-02-15 00:00:00.000 0
EDIT : The above method may not work for all set of data. See the first comment from Leszek Gniadkowski. Here is another alternate
select
empid,
work_date ,
case when
sum(floor(working_hours)*60+(working_hours-floor(working_hours))*100+
floor(ot_hours)*60+(ot_hours-floor(ot_hours))*100+
floor(break_hours)*60+(break_hours-floor(break_hours))*100) >=480
then 1 else 0
end as status
from
#t
group by
empid,work_date
Post in the commet section if you have any other method.