I'm trying to calculate the time a computer is on, I simply have a on_time and an off_time, I need to calculate the time the computer is on between 2 different rates so I can calculate savings. For example a day_rate which is from 07:00 - 22:59 and a night rate from 23:00 - 06:59. the following is my current stored procedure with sample Data, if you run it you can see the 1st record calculates perfectly (it being on for nearly 5hours on the day rate and just over 2 hours on the night rate) however the 2nd record does not calculate correctly, the problem seems to be if the time starts on the night_rate and runs into the day_rate it only calculates the hours the computer is on in the day_rate not the night rate. Apolgises if i havent explained my problem well but if you run the sample stored procedure you will see my problem. Would apprecite any help as im not too sure how to resolve this and if my SQL is correct.ThanksCREATE PROCEDURE [dbo].[TEST_2RATES] AS/* Create temp table */ CREATE TABLE #costtemp ( cost_id int, pc_profile_id int, pc_name varchar(50), on_time datetime, off_time datetime, subpolicy_name varchar(50), pc_description varchar(50), hours_on_day float, day_hour_rate float, hours_on_night float, night_hour_rate float, pc_kwh_rate float, status nchar(10), cost float ) /** Insert Values into Temp Table from View, including Day/Night Rates*/ insert into #costtemp (cost_id, pc_profile_id, on_time, off_time, status, subpolicy_name, day_hour_rate, night_hour_rate, pc_kwh_rate)SELECT '8', '8', '09/11/2009 18:12:10', '09/12/2009 01:12:50', 'CLOSED', 'Manage', '1.2','3.9', '1.9' UNION ALLSELECT '9', '9', '09/09/2009 05:00:00', '09/09/2009 12:00:00', 'CLOSED', 'Finance', '1.2','3.9', '1.9'/** Get cost of PC's*/ UPDATE #costtempSET hours_on_day = isnull(cost.hours_on_day, 0) ,hours_on_night = isnull(cost.hours_on_night, 0),cost = (isnull(cost.hours_on_day, 0) * pc_kwh_rate * day_hour_rate) + (isnull(cost.hours_on_night, 0) * pc_kwh_rate * night_hour_rate)FROM #costtemp inner join (select cost_id, sum(datediff(MINUTE, day_start, day_end))/ 60.0 as hours_on_day, sum(datediff(MINUTE, night_start, night_end))/ 60.0 as hours_on_nightfrom ( select cost_id, pc_profile_id, on_time, off_time, subpolicy_name, day_hour_rate, night_hour_rate, pc_kwh_rate, status, start1, finish1, start2, finish2, offset, -- Either return null, or the start of the day period or the shutdown_time. The null value is to know when to stop counting case when off_time < case when on_time < start1 then start1 else case when on_time < finish1 then on_time else finish1 end -- Provides a stoping condition, when the field day_start begins to be NULL -- means that the day and night intervals don't fall in the shutdown/start period end then null else case when on_time < start1 then start1 else case when on_time < finish1 then on_time else finish1 end end end as day_start, -- Either returns the finish of the day period or the startup_time case when off_time < finish1 then off_time else finish1 end as day_end, -- Either returns the start of the night period or the startup_time case when off_time > start2 then start2 else off_time end as night_start, -- Either return the finish of the night period or the startup_time case when off_time < finish2 then off_time else finish2 end as night_end from ( select cost_id, pc_profile_id, on_time, off_time, subpolicy_name, day_hour_rate, night_hour_rate, pc_kwh_rate, status, -- Start time for the day period convert(datetime, left(convert(varchar, dateadd(d, offset, on_time), 120), 11) + '07:00:00', 120) start1, -- Finish time for the day period convert(datetime, left(convert(varchar, dateadd(d, offset, on_time), 120), 11) + '22:59:00', 120) finish1, -- Start time for the night period convert(datetime, left(convert(varchar, dateadd(d, offset, on_time), 120), 11) + '23:00:00', 120) start2, -- Finish time for the night period convert(datetime, left(convert(varchar, dateadd(d, offset + 1, on_time), 120), 11) + '06:59:00', 120) finish2, offset from #costtemp cross join ( -- Provides a 10 row table with sequencial numbers from 0 to 9 -- This allows to have off states that last for 9 days select top 90 row_number() over(order by id) -1 as offset from syscolumns ) numbers where status = 'CLOSED' ) periods)a-- Stopping conditionwhere day_start is not nullgroup by cost_id) cost on #costtemp.cost_id = cost.cost_idSelect * from #costtempRETURN
niall