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 2008 Forums
 Transact-SQL (2008)
 Need to improve function performance

Author  Topic 

silver_surfer21
Starting Member

21 Posts

Posted - 2011-03-09 : 10:14:16
I have this function
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
CREATE FUNCTION FindCurrentValue
(
-- Add the parameters for the function here
@Postcode nvarchar(50),@Application_Date date,@HouseType nvarchar(50), @decPrice money
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE @currentValue money
DECLARE @CurrentYear int
DECLARE @CurrentMonth int
DECLARE @NoOfLoops int
DECLARE @CurrentLoop int
DECLARE @CurrentAverage decimal

SET @CurrentYear = YEAR(@Application_Date)
SET @currentValue = @decPrice
set @CurrentMonth = MONTH(@Application_DATE)

WHILE(@CurrentYear <=YEAR(GETDATE()))
BEGIN
SET @CurrentLoop =0


IF(YEAR(GETDATE()) = @CurrentYear)
BEGIN
SET @NoOfLoops = MONTH(GETDATE())-@CurrentMonth
END

IF(@CurrentYear = YEAR(@Application_Date))
BEGIN
SET @NoOfLoops = 12 - MONTH(@Application_Date)
END

IF(@CurrentYear >YEAR(@Application_Date) AND @CurrentYear < YEAR(GETDATE()))
BEGIN
SET @NoOfLoops = 12
END

SELECT @CurrentAverage = (SELECT Top 1 Avg_Monthly_Increase FROM YearlyAverageIncrease WHERE @Postcode = Postcode AND @HouseType = HouseType AND YEAR = @CurrentYear)


WHILE(@CurrentLoop < @NoOfLoops)
Begin

-- Add the T-SQL statements to compute the return value here
SET @currentValue = @CurrentValue + ((@currentValue/100) * @CurrentAverage)

SET @CurrentLoop = @CurrentLoop +1
END

Set @CurrentYear = @CurrentYear +1
SET @CurrentLoop = @CurrentLoop +1
END


-- Return the result of the function
RETURN @currentValue

END


which takes data about a property and its price when bought, and uses an average of price increases on that type of property in order to calculate an estimate of what that property should be worth now. As far as I can tell everything works properly but the function is horribly slow, taking around 15 minutes to calculate the predicted value for one record. This is not really feasible for the number of records I need to run through it, and so I'm wondering if there's any way to speed the process up.

I suspect the loops are horribly inefficient being new to sql don't know a way around using them

bals
Starting Member

4 Posts

Posted - 2011-03-10 : 10:16:59
It has 2 while loops ,with nested loop. thats why it take lot of time.
Use Tally or numbers table rather than using loop
http://www.sqlservercentral.com/articles/T-SQL/62867/

Else provide create script and sample data for YearlyAverageIncrease
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-03-10 : 10:53:19
This will outperform your current loop-function.

CREATE FUNCTION dbo.fnFindCurrentValue
(
@PostCode NVARCHAR(50),
@ApplicationDate DATE,
@HouseType NVARCHAR(50),
@Price MONEY
)
RETURNS INT
AS
BEGIN
RETURN (
SELECT @Price * EXP(SUM(LOG(1 + x.CurrentAverage / 100E)))
FROM (
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6 UNION ALL
SELECT 7 UNION ALL
SELECT 8 UNION ALL
SELECT 9 UNION ALL
SELECT 10 UNION ALL
SELECT 11
) AS m(Iterations)
CROSS JOIN (
SELECT TOP(1)
Avg_Monthly_Increase
FROM dbo.YearlyAverageIncrease
WHERE PostCode = @PostCode
AND HouseType = @HouseType
AND [Year] = DATEPART(YEAR, @ApplicationDate)
AND Avg_Monthly_Increase > -100
) AS x(CurrentAverage)
WHERE m.Iterations >= DATEPART(MONTH, @Application_Date)
)
END


N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-03-11 : 04:20:34
Any progress yet?



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

silver_surfer21
Starting Member

21 Posts

Posted - 2011-03-11 : 04:48:58
Having to deal with something else first, hoping to try out your suggestions today and get back to you on any progress. Thanks very much for everything so far!
Go to Top of Page

silver_surfer21
Starting Member

21 Posts

Posted - 2011-03-11 : 11:16:09
I've only been able to try a cursory check so far but it looks like Peso's code is working well without even requiring any changes other than a slight typo in one of the variables. :) Thank you very much
Go to Top of Page
   

- Advertisement -