Before posting I have read few articles about developing USD functions, but have not encountered solutions for my problem... which is as follows:
I have a very simple database, which stores basketball players and consists of ID, Age, Height and Name column. What I would like to do is to implement a function 'height' with one parameter @set varchar(10), that depending one @set value will trigger off different select statements
what I was trying to implement was in psuedo-code:
CREATE FUNCTION [dbo].[age](@set varchar(10))
RETURNS TABLE
AS
BEGIN
IF (@set = 'tall')
SELECT * from player where height > 180
ELSE IF (@set = 'average')
SELECT * from player where height >= 155 and height <=175
ELSE IF (@set = 'low')
SELECT * from player where height < 155
END
Could anyone give me a hint how to implement it?
You were close. Using a multi-statement table-valued function requires the return table to be specified and populated in the function:
CREATE FUNCTION [dbo].[age](@set varchar(10))
RETURNS @Players TABLE
(
-- Put the players table definition here
)
AS
BEGIN
IF (@set = 'tall')
INSERT INTO @Players SELECT * from player where height > 180
ELSE IF (@set = 'average')
INSERT INTO @Players SELECT * from player where height >= 155 and height <=175
ELSE IF (@set = 'low')
INSERT INTO @Players SELECT * from player where height < 155
RETURN -- @Players (variable only required for Scalar functions)
END
I would recommend using an inline TVF as Richard's answer demonstrates. It can infer the table return from your statement.
Note also that a multi-statement and inline TVFs are really quite different. An inline TVF is less of a black-box to the optimizer and more like a parametrized view in terms of the optimizer being able to rearrange things with other tables and views in the same execution plan.
The simplest form is always the best
CREATE FUNCTION [dbo].[age](@set varchar(10))
RETURNS TABLE
AS RETURN
SELECT * from player
where ((@set = 'tall' and height > 180)
or (@set = 'average' AND height >= 155 and height <=175)
or (@set = 'low' AND height < 155))
GO
This form is called INLINE table function, which means SQL Server is free to expand it to join player directly to other tables in-line of a greater query, making it perform infinitely1 better than a multi-statement table valued function.
You may prefer this though, so that your ranges are complete (you have a gap between 175 and 180)
where ((@set = 'tall' and height > 180)
or (@set = 'average' AND height >= 155 and height <= 180)
or (@set = 'low' AND height < 155))
SQL Server takes care of short circuiting the branches when the variable @set is parsed.
1 exaggeration, but only slightly
Why are you hardcoding this, create a heights table and then grab all the heights that are valid for the range
SELECT * from player p
join Heights h on p.height between h.heightStart and h.heightEnd
WHERE h.height = @set
This should work.
SELECT * FROM player
WHERE
height > CASE
WHEN @set = 'tall' THEN 180
WHEN @set = 'average' THEN 154
WHEN @set = 'low' THEN 0
END
I'll leave the < case for your enjoyment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With