views:

51

answers:

3

How would one go about converting this into a scalar UDF? I'll pass the product_id to the UDF.

Running SQL 2k5

 SELECT 
 sum(qty) as qty,
  product_id
  FROM  vProductQuantity
 WHERE 
 product_id = @product_id
 GROUP BY product_id
+1  A: 

Edit Undeleted in case you decide to go this route...

   CREATE FUNCTION [dbo].[products]
        (
        @product_id int
        )
    RETURNS TABLE
    AS RETURN
        (
    SELECT 
     sum(qty) as qty,
      product_id
      FROM  vProductQuantity
     WHERE 
     product_id = @product_id
    )
Martin Smith
Inline TVFs like this will generally perform better than a scalar UDF, as the optimizer does a better job. Typical usage is as: SELECT t.*, products.qty FROM t OUTER APPLY [dbo].[products](t.product_id) AS products
Cade Roux
Also - if at all possible, resist the temptation to create a multi-statement TVF - these are not able to be optimized the same way as inline TVFs.
Cade Roux
+1  A: 

Here is how you would create the UDF so that it will return the integer value of product quantity.

CREATE FUNCTION getProductQuantity (
   @product_id int
   )   
RETURNS int  
AS  
BEGIN  
  DECLARE @Return int
  SELECT   @Return = sum(qty) as qty   FROM  vProductQuantity  WHERE   product_id = @product_id  GROUP BY product_id

  RETURN @return  
END

As Martin answered, create it as a table valued function to return multiple values.

Joe King
He doesn't specify scalar UDF - guess we'll need that clarified!
Martin Smith
scalar, right thats whats I need
jeff
Looking for single value to be returned
jeff
Good stuff. I guessed wrong then! I think this answer should do the job but needs a slight tweak `SELECT @Return = sum(qty) FROM vProductQuantity WHERE product_id = @product_id`
Martin Smith
@Martin Smith - your original answer will perform better than a scalar function. I tried to add this comment as you were deleting it: Inline TVFs like this will generally perform better than a scalar UDF, as the optimizer does a better job. Typical usage is as: SELECT t.*, products.qty FROM t OUTER APPLY [dbo].[products](t.product_id) AS products
Cade Roux
@Cade I've restored it. I agree with your remarks RE: Performance on Scalar functions.
Martin Smith
+2  A: 

I strongly recommend you not use scalar UDFs for any significant processing. For individual calls, it's not bad, but calling it for any significant number of rows generally performs very poorly.

If you were to call this for multiple products in some other rowset the UDF will not scale well.

A view or inline table-valued function will perform far better: i.e.

CREATE VIEW vQuantity AS
SELECT 
 sum(qty) as qty,
  product_id
  FROM  vProductQuantity
 GROUP BY product_id

and

SELECT *
FROM t
LEFT JOIN vQuantity ON vQuantity.product_id = t.product_id

or

CREATE FUNCTION udfQuantity(any params) RETURNS TABLE AS
RETURN (
    SELECT 
     sum(qty) as qty,
      product_id
      FROM  vProductQuantity
     GROUP BY product_id
)

and

SELECT *
FROM t
LEFT JOIN udfQuantity(any params) AS Quantity ON Quantity.product_id = t.product_id

I strongly recommend you review the execution plan of any process where you use a scalar UDF.

Cade Roux