tags:

views:

25

answers:

2

I have a SQL Server function which converts a nvarchar day duration setting into a datetime value.

The day duration format is >days<.>hours<:>minutes<, for instance 1.2:00 for one day and two hours.

The format of the day duration setting can not be changed, and we can be sure that all data is correctly formatted and present.

Giving the function a start time and the day duration setting it should return the end time.

For instance: 2010-01-02 13:30 ==> 2010-01-03 2:00

I'm using a combination of charindex, substring and convert methods to calculate the value, which is kind of slow and akward. Is there any other way to directly convert this day duration setting into a datetime value?

+1  A: 

Not from what I can see. I would end up with a similar bit of SQL like you, using charindex etc. Unfortunately it's down to the format the day duration is stored in. I know you can't change it, but if it was in a different format then it would be a lot easier - the way I'd usually do this for example, is to rationalise the duration down to a base unit like minutes.

Instead of storing 1.2:00 for 1 day and 2 hours, it would be (1 * 24 * 60) + (2 * 60) = 1560. This could then be used in a straightforward DATEADD on the original date (date part only).

With the format you have, all approaches I can think of involve using CHARINDEX etc.

AdaTheDev
Yeah ... I know that but unfortunately the format is somehow legacy and I can not change it as it is used in some other systems.
Drejc
@Drejc - I don't think there's another way round it to be honest. Is it definitely the cause of slow performance? The other thing I'd suggest is to not do the calculation in SQL Server, but return both fields as-is and let the calling code do it that will perform better at string manipulation
AdaTheDev
This is actually done the way you are describing except for one situation, where the calculation must be performed on the SQL side.It's not causing any slow responses or similar problems but it is just an ugly solution.
Drejc
@Drejc - that's one thing at least. You've wrapped it in a function which at least keeps it in one place, nicely separated away.
AdaTheDev
+1  A: 

One alternative would be to build a string with the calculation. Then you can run the generated SQL with sp_executesql, specifying @enddate as an output parameter:

declare @startdate datetime
declare @duration varchar(10)
declare @enddate datetime

set @startdate = '2010-01-02 13:30'
set @duration = '0.12:30'

declare @sql nvarchar(max)
set @sql = 'set @enddate = dateadd(mi,24*60*' + 
    replace(replace(@duration,'.','+60*'),':','+') + ', @startdate)'
exec sp_executesql  @sql,
    N'@startdate datetime, @enddate datetime out', 
    @startdate, @enddate out

This creates a string containing set @enddate = dateadd(mi,24*60*0+60*12+30, @startdate) and then runs it.

I doubt this is faster than the regular charindex way:

declare @pos_dot int
declare @day int
declare @hour int
declare @minute int

select 
    @pos_dot = charindex('.',@duration),
    @day = cast(left(@duration, @pos_dot-1) as int),
    @hour = cast(left(right(@duration, 5), 2) as int),
    @minute = cast(right(@duration, 2) as int),
    @enddate = dateadd(mi, 24*60*@day + 60*@hour + @minute, @startdate)
Andomar
Huh ... it's certainly a way to do it, but it highly unreadable and the next person looking at this will just say FTW ;)
Drejc
You asked for a solution without charindex tho ;)
Andomar
+1, awesome! this show why CHARINDEX is important!! you might make you charindex version more simple with a LEFT() for the days and a RIGHT() for the minutes
KM
@Andomar true ... my fault ;)
Drejc