Chris Wood
Chris Wood

Reputation: 575

sql scalar functions

I have a scalar function in my code that calls another scalar function that calls 2 other tables as detailed below. I know this must be performing like a pig. It is used throughout the database... My problem is its a little outside developing skills to rewrite this as an table valued function.

I'm attempting to win some of the developers over to rewriting the function, but we only have JAVA guys and no dedicated SQL developer, so they dont see any problems. can anyone suggest how this should be rewritten? many thanks...

CREATE FUNCTION [dbo].[getInvertCurrencyExchangeRateByDate](@casino_id char(16),@currency_code char(3), @end_date datetime)
RETURNS float AS
BEGIN

declare @retval float;

set @retval = 
dbo.getCurrencyExchangeRateByDate(@casino_id,@currency_code,@end_date);

if (@retval != 0) return 1/@retval;
return 0;
END

CREATE FUNCTION [dbo].[getCurrencyExchangeRateByDate](@casino_id char(16),@currency_code char(3), @end_date datetime)
RETURNS float AS
BEGIN

declare @retval float;
declare @casino_curr_code char(3);

set @casino_curr_code = 
(SELECT TOP 1 currency_code
FROM Casino
WHERE
casino_id=@casino_id 
);

if (@currency_code = @casino_curr_code) return 1;

set @retval = 
COALESCE(
(
SELECT TOP 1 exchange_rate
FROM CurrencyExchangeRateHistory
WHERE 
casino_id=@casino_id and 
currency_code=@currency_code AND 
transact_time <= @end_date
ORDER BY 
transact_time DESC
),0.0);

return @retval
END

Upvotes: 3

Views: 8170

Answers (1)

Thiago Dantas
Thiago Dantas

Reputation: 690

I'm sorry, but thats a heck lot of code for something rather simple I think this satisfies the query needs.

CREATE FUNCTION dbo.TVF(@casino_id char(16),@currency_code char(3), @end_date datetime)
RETURNS TABLE
AS
RETURN                          --IF THE JOIN FAILS OR RETURNS 0, DIVISION WILL NEVER HAPPEN AND FALL IN THE ISNULL
    SELECT TOP 1 CASE WHEN A.currency_code = @currency_code THEN 1 ELSE ISNULL(1/NULLIF(B.exchange_rate,0), 0) END AS RETVAL
    FROM Casino A
    LEFT JOIN CurrencyExchangeRateHistory B ON A.casino_id = B.casino_id AND B.transact_time <= @end_date AND B.currency_code = A.currency_code
    WHERE A.casino_id = @casino_id
    ORDER BY B.transact_time DESC

Upvotes: 3

Related Questions