Tsql IF...CASE returns syntax error - tsql

Much time has been invested in searching for the error. I used 2 other working functions as guides in constructing this, but alas, I am thus far defeated. Can someone tell me why this is returning a syntax error:
FUNCTION FN_USER_MATRIX_PriceTweak
(
#Cost float, #CostAvg float,
#Tier1MaxVal float, #Tier1Mult float,
#Tier2MaxVal float, #Tier2Mult float,
#Tier3MaxVal float, #Tier3Mult float,
#Tier4MaxVal float, #Tier4Mult float,
#Tier5MaxVal float, #Tier5Mult float,
#Above5Mult float
)
RETURNS float
AS
BEGIN
DECLARE #Result float
SET #Result =
(
IF #Cost <= #CostAvg
CASE
WHEN #Cost <= #Tier1MaxVal THEN #Cost * #Tier1Mult
WHEN #Cost <= #Tier2MaxVal THEN #Cost * #Tier2Mult
WHEN #Cost <= #Tier3MaxVal THEN #Cost * #Tier3Mult
WHEN #Cost <= #Tier4MaxVal THEN #Cost * #Tier4Mult
WHEN #Cost <= #Tier5MaxVal THEN #Cost * #Tier5Mult
ELSE #Cost * #Above5Mult
ELSE
CASE
WHEN #CostAvg <= #Tier1MaxVal THEN #CostAvg * #Tier1Mult
WHEN #CostAvg <= #Tier2MaxVal THEN #CostAvg * #Tier2Mult
WHEN #CostAvg <= #Tier3MaxVal THEN #CostAvg * #Tier3Mult
WHEN #CostAvg <= #Tier4MaxVal THEN #CostAvg * #Tier4Mult
WHEN #CostAvg <= #Tier5MaxVal THEN #CostAvg * #Tier5Mult
ELSE #CostAvg * #Above5Mult
)
RETURN #Result
END
My error messages:
Msg 156, Level 15, State 1, Procedure FN_USER_MATRIX_PriceTweak, Line 21
Incorrect syntax near the keyword 'IF'.
Msg 156, Level 15, State 1, Procedure FN_USER_MATRIX_PriceTweak, Line 22
Incorrect syntax near the keyword 'CASE'.

Please try this:
IF #Cost <= #CostAvg
BEGIN
SET #Result = CASE
WHEN #Cost <= #Tier1MaxVal THEN #Cost * #Tier1Mult
WHEN #Cost <= #Tier2MaxVal THEN #Cost * #Tier2Mult
WHEN #Cost <= #Tier3MaxVal THEN #Cost * #Tier3Mult
WHEN #Cost <= #Tier4MaxVal THEN #Cost * #Tier4Mult
WHEN #Cost <= #Tier5MaxVal THEN #Cost * #Tier5Mult
ELSE #Cost * #Above5Mult
END
END
ELSE
BEGIN
SET #Result = CASE
WHEN #CostAvg <= #Tier1MaxVal THEN #CostAvg * #Tier1Mult
WHEN #CostAvg <= #Tier2MaxVal THEN #CostAvg * #Tier2Mult
WHEN #CostAvg <= #Tier3MaxVal THEN #CostAvg * #Tier3Mult
WHEN #CostAvg <= #Tier4MaxVal THEN #CostAvg * #Tier4Mult
WHEN #CostAvg <= #Tier5MaxVal THEN #CostAvg * #Tier5Mult
ELSE #CostAvg * #Above5Mult
END
END
RETURN #Result

You should be using a nested CASE where you have your IF...ELSE:
SET #Result =
(
CASE WHEN #Cost <= #CostAvg THEN (
CASE
WHEN #Cost <= #Tier1MaxVal THEN #Cost * #Tier1Mult
WHEN #Cost <= #Tier2MaxVal THEN #Cost * #Tier2Mult
WHEN #Cost <= #Tier3MaxVal THEN #Cost * #Tier3Mult
WHEN #Cost <= #Tier4MaxVal THEN #Cost * #Tier4Mult
WHEN #Cost <= #Tier5MaxVal THEN #Cost * #Tier5Mult
ELSE #Cost * #Above5Mult END)
ELSE
(CASE
WHEN #CostAvg <= #Tier1MaxVal THEN #CostAvg * #Tier1Mult
WHEN #CostAvg <= #Tier2MaxVal THEN #CostAvg * #Tier2Mult
WHEN #CostAvg <= #Tier3MaxVal THEN #CostAvg * #Tier3Mult
WHEN #CostAvg <= #Tier4MaxVal THEN #CostAvg * #Tier4Mult
WHEN #CostAvg <= #Tier5MaxVal THEN #CostAvg * #Tier5Mult
ELSE #CostAvg * #Above5Mult END)
END
)

Related

Retutring from a function using case

Here is my postgres function:
create or replace function fail_hold_pay_count_metric()
returns table (
fail_count int,
hold_pay_count int
)
as
$$
declare
total_count int;
fail_count int;
hold_pay_count int;
required_rows_count int;
percent_count int;
begin
select count(1) as total_count,
sum(case when status = 'FAIL' then 1 else 0 end) as fail_count,
sum(case when status = 'HOLD_PAY' then 1 else 0 end) as hold_pay_count
into total_count, fail_count, hold_pay_count
from bundle where updated_at > (now() - interval '1 year');
if total_count > 10
then
required_rows_count := (select fail_count + hold_pay_count);
percent_count := (select (required_rows_count / total_count * 100));
end if;
return query (select case when (percent_count > 50) then (fail_count, hold_pay_count) else (0, 0) end);
end;
$$ language plpgsql;
I need to return (0,0) if percent_count was lower than 50. My function doesn't work. Where did I make a mistake?
You are returning a single column of a row type instead of a row of two int types.
Please try this, instead:
return query select case when percent_count > 50 then fail_count else 0 end,
case when percent_count > 50 then hold_pay_count else 0 end;

postgres function - declare variable with select statement

i have modifed my function, but i have problems with declare variables. I used postgres 8.4. Have someone an idea?
Function:
CREATE OR REPLACE FUNCTION requestcounterid(_mindate timestamptz, _maxdate timestamptz)
RETURNS TABLE (kategorien text, requestcounter int) AS
$func$
DECLARE
_minid bigint;
_maxid bigint;
BEGIN
_minid := (SELECT id from tablename where starttime >= $1 ORDER BY tablename2 ASC LIMIT 1);
_maxid := (SELECT id from tablename where starttime < $2 ORDER BY tablename2 DESC LIMIT 1);
SELECT CASE WHEN duration <= 10000000 THEN '00-01 sec'::text
WHEN duration <= 40000000 THEN '01-04 sec'
WHEN duration <= 100000000 THEN '04-10 sec'
WHEN duration <= 300000000 THEN '10-30 sec'
WHEN duration <= 600000000 THEN '30-60 sec'
ELSE 'more than 60 sec' END
, count(*)::int
FROM tablename
WHERE id >= _minid and id <= _maxid
GROUP BY 1
ORDER BY 1;
END;
$func$ LANGUAGE plpgsql;
Error:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function "requestcounterid" line 11 at SQL statement
Regrads
Now it workes:
CREATE OR REPLACE FUNCTION requestcounterid(_mindate timestamptz, _maxdate timestamptz)
RETURNS TABLE (kategorien text, requestcounter int) AS
$func$
DECLARE
_minid bigint;
_maxid bigint;
BEGIN
SELECT id INTO _minid from tablename where starttime >= $1 ORDER BY starttime ASC LIMIT 1;
SELECT id INTO _maxid from tablename where starttime < $2 ORDER BY starttime DESC LIMIT 1;
Return Query SELECT CASE WHEN duration <= 10000000 THEN '00-01 sec'::text
WHEN duration <= 40000000 THEN '01-04 sec'
WHEN duration <= 100000000 THEN '04-10 sec'
WHEN duration <= 300000000 THEN '10-30 sec'
WHEN duration <= 600000000 THEN '30-60 sec'
ELSE 'more than 60 sec' END
, count(*)::int
FROM tablename
WHERE id >= _minid and id <= _maxid
GROUP BY 1
ORDER BY 1;
END;
$func$ LANGUAGE plpgsql;

Function that creates unique reference no with sql server 2008

I have an asp.net application that uses SQL Server 2005. In this application I want to create a function that returns unique reference numbers for new Inquiry Id.
I read about UNIQUEIDENTIFIER but it has a specific format like 1548C3E02-2D73-4244-8787-D45AC590519A.
I want output like 1703-HJIF-2012. Here first have combination of current datepart like date and month, second is random string which auto generate and third one is year part of current date. I don't have any idea how I could create such a function and how I would be calling this function from a stored procedure and get result string from function with this required format.
here some one posted me this function but this generates spaces instead of 0 :
create function UniqueRefNum (#r1 float, #r2 float, #r3 float, #r4 float)
returns char(14)
begin
-- Not sure if rand() might return 1.0
-- If it does, the conversion code below would produce a character that's not an
-- uppercase letter so let's avoid it just in case
if #r1 = 1.0 set #r1 = 0
if #r2 = 1.0 set #r2 = 0
if #r3 = 1.0 set #r3 = 0
if #r4 = 1.0 set #r4 = 0
declare #now datetime
set #now = getdate() -- or getutcdate()
declare #m char(2)
if month(#now) < 10
set #m = '0' + month(#now)
else
set #m = month(#now)
declare #d char(2)
if day(#now) < 10
set #d = '0' + day(#now)
else
set #d = day(#now)
return #m + #d + '-' +
char(65 + cast(#r1 * 26 as int)) +
char(65 + cast(#r2 * 26 as int)) +
char(65 + cast(#r3 * 26 as int)) +
char(65 + cast(#r4 * 26 as int)) +
'-' + cast(year(#now) as varchar)
end
You then call the function from your stored procedure like this:
declare #uniqueRef char(14)
set #uniqueRef = dbo.UniqueRefNum(rand(), rand(), rand(), rand())
---------------Updated-----------------------------
it's generates out put is like that :
4 24-HHBH-2014
and i want output something like this :
2404-HHBH-2014
DDMM-XXXX-YYYY
You need to cast the day/month values to char before concatenating the strings.
declare #m char(2)
if month(#now) < 10
set #m = '0' + cast(month(#now) as char(1))
else
set #m = month(#now)
declare #d char(2)
if day(#now) < 10
set #d = '0' + cast(day(#now) as char(1))
else
set #d = day(#now)
The thing is that the string in '0' + month(#now) is converted to integer and then the two numbers are added up.

Convert Hijri Shamsi date format tsql

I want convert my Hijri Shamsi date '92/2/3' to this format : '92/02/03'
With this code, I get this error :The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
Declare #Str Varchar(10) = '92/2/3'
Select Convert(Varchar(10), Convert(DateTime, #Str), 111)
How can i change format of date ?
Since you don't have centuries you should use 11, not 111 as your conversion code
You need to use 11 in the inner convert to tell it what format it is converting FROM
Declare #Str Varchar(10) = '92/2/3'
Select Convert(Varchar(10), Convert(DateTime, #Str,11), 11)
Use this functions to convert Gregorian date to Hijri(Shamsi) date with your requested format:
CREATE FUNCTION [dbo].[ShamsiDate]
(
#ChirsDate SMALLDATETIME
)
RETURNS CHAR(10)
AS
BEGIN
DECLARE #SolarDate CHAR(10)
DECLARE #Day CHAR(2)
DECLARE #Mon CHAR(2)
DECLARE #SDay INT
DECLARE #SMon INT
DECLARE #SYear INT
SET #SYear = dbo.ShamsiDatePart(#ChirsDate, 'Y')
SET #SMon = dbo.ShamsiDatePart(#ChirsDate, 'M')
SET #SDay = dbo.ShamsiDatePart(#ChirsDate, 'D')
IF #SMon <= 9
SELECT #Mon = '0' + CONVERT(CHAR(1), #SMon)
ELSE
SELECT #Mon = CONVERT(CHAR(2), #SMon)
IF #SDay <= 9
SELECT #Day = '0' + CONVERT(CHAR(1), #SDay)
ELSE
SELECT #Day = CONVERT(CHAR(2), #SDay)
SELECT #SolarDate = CONVERT(CHAR(4), #SYear) + '/' + #Mon + '/'
+ #Day
RETURN #SolarDate
END
CREATE FUNCTION [dbo].[ShamsiDatePart]
(
#MiDate DATETIME ,
#ADatePart CHAR
)
RETURNS INT
AS
BEGIN
DECLARE #TmpY INT ,
#Leap INT
DECLARE #Sh_Y INT ,
#Sh_M INT ,
#Sh_D INT ,
#Result INT
IF #MiDate IS NULL
RETURN 0
DECLARE #Result INT
SET #Result = CONVERT(INT, CONVERT(FLOAT, #MiDate))
IF #Result <= 78
BEGIN
SET #Sh_Y = 1278
SET #Sh_M = ( #Result + 10 ) / 30 + 10
SET #Sh_D = ( #Result + 10 ) % 30 + 1
END
ELSE
BEGIN
SET #Result = #Result - 78
SET #Sh_Y = 1279
WHILE 1 = 1
BEGIN
SET #TmpY = #Sh_Y + 11
SET #TmpY = #TmpY - ( #TmpY / 33 ) * 33
IF ( #TmpY <> 32 )
AND ( ( #TmpY / 4 ) * 4 = #TmpY )
SET #Leap = 1
ELSE
SET #Leap = 0
IF #Result <= ( 365 + #Leap )
BREAK
SET #Result = #Result - ( 365 + #Leap )
SET #Sh_Y = #Sh_Y + 1
END
IF #Result <= 31 * 6
BEGIN
SET #Sh_M = ( #Result - 1 ) / 31 + 1
SET #Sh_D = ( #Result - 1 ) % 31 + 1
END
ELSE
BEGIN
SET #Sh_M = ( ( #Result - 1 ) - 31 * 6 ) / 30 + 7
SET #Sh_D = ( ( #Result - 1 ) - 31 * 6 ) % 30 + 1
END
END
RETURN CASE #ADatePart WHEN 'Y' THEN #Sh_Y WHEN 'M' THEN #Sh_M WHEN 'D' THEN #Sh_D ELSE 0 END
END
You can use the give below solution, if you are using SQL Server 2012.
Declare #Str varchar(10) = '92/2/3'
Select Format(Convert(Date, #Str,11),'yy/MM/dd')
Imran

operations with time firebird

To resolve the issue.
There are two meanings Time: 12:20 and 23:55. How can add the values that-be at the outlet was 36:15.
Or how to keep these values in dB (Time) Time except that, were it possible addition?
Firebird's data type TIME allows range between 00:00:00 and 24:00:00 only.
If you want to store arbitrary amount of time (say, in seconds) use INTEGER or NUMERIC datatype. Then convert it into time string format if needed.
You can use TIMESTAMP in dialect 3
With this you can add 2 times.
i have code here convert seconds in integer
CREATE PROCEDURE P_CONVERT_TIME (
V_TIME_INT INTEGER
)
RETURNS (
V_TIME_STR VARCHAR(20)
)
AS
DECLARE VARIABLE v_max_trans_hour integer;
DECLARE VARIABLE v_max_trans_min integer;
DECLARE VARIABLE v_max_trans_sec integer;
DECLARE VARIABLE v_max_trans_sec_gross integer;
BEGIN
v_max_trans_sec = cast(v_Time_Int as integer);
v_max_trans_hour = coalesce(div(v_max_trans_sec, 3600), 0);
if (v_max_trans_hour > 0) then
v_max_trans_sec = v_max_trans_sec - (3600 * v_max_trans_hour);
v_max_trans_min = coalesce(div(v_max_trans_sec, 60), 0);
if (v_max_trans_min > 0) then
v_max_trans_sec = v_max_trans_sec - (60 * v_max_trans_min);
if (v_max_trans_hour > 0) then begin
if (v_max_trans_hour < 10) then begin
V_Time_Str ='0'||v_max_trans_hour||':'; end else
V_Time_Str=v_max_trans_hour||':';
end else V_Time_Str='00:';
if (v_max_trans_min > 0) then begin
if (v_max_trans_min <10) then begin
V_Time_Str =V_Time_Str ||'0'||v_max_trans_min||':'; end else
V_Time_Str =V_Time_Str ||v_max_trans_min||':';
end else V_Time_Str =V_Time_Str ||'00:';
if (v_max_trans_sec > 0) then begin
if (v_max_trans_sec <10) then begin
V_Time_Str =V_Time_Str ||'0'|| v_max_trans_sec; end else
V_Time_Str =V_Time_Str || v_max_trans_sec;
end else V_Time_Str =V_Time_Str ||'00';
suspend;
END
;