преобразовать в UDF из оператора select

Как можно было бы преобразовать это в скалярную UDF? Я передам product_id в UDF.

Запуск SQL 2k5

 SELECT 
 sum(qty) as qty,
  product_id
  FROM  vProductQuantity
 WHERE 
 product_id = @product_id
 GROUP BY product_id

person jeff    schedule 06.05.2010    source источник


Ответы (3)


Я настоятельно рекомендую вам не использовать скалярные пользовательские функции для какой-либо значительной обработки. Для отдельных вызовов это неплохо, но вызов для любого значительного количества строк обычно работает очень плохо.

Если бы вы вызывали это для нескольких продуктов в каком-то другом наборе строк, UDF не будет хорошо масштабироваться.

Представление или встроенная функция с табличным значением будут работать намного лучше: т.е.

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

и

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
)

и

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

Я настоятельно рекомендую вам просмотреть план выполнения любого процесса, в котором вы используете скалярную UDF.

person Cade Roux    schedule 06.05.2010

Вот как вы могли бы создать UDF, чтобы он возвращал целочисленное значение количества продукта.

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

Как ответил Мартин, создайте его как функцию с табличным значением, чтобы возвращать несколько значений.

person Joe King    schedule 06.05.2010
comment
Он не указывает скалярную определяемую пользователем функцию — думаю, нам нужно это уточнить! - person Martin Smith; 07.05.2010
comment
Поиск единственного возвращаемого значения - person jeff; 07.05.2010
comment
Хорошая вещь. Я тогда неправильно угадал! Я думаю, что этот ответ должен подойти, но нуждается в небольшой настройке SELECT @Return = sum(qty) FROM vProductQuantity WHERE product_id = @product_id - person Martin Smith; 07.05.2010
comment
@Martin Smith - ваш исходный ответ будет работать лучше, чем скалярная функция. Я попытался добавить этот комментарий, когда вы его удаляли: встроенные TVF, подобные этому, обычно работают лучше, чем скалярная UDF, поскольку оптимизатор работает лучше. Типичное использование: SELECT t.*, products.qty FROM t OUTER APPLY [dbo].[products](t.product_id) AS products - person Cade Roux; 07.05.2010
comment
@Cade Я восстановил его. Я согласен с вашими замечаниями RE: производительность скалярных функций. - person Martin Smith; 07.05.2010

Изменить Восстановить, если вы решите пойти по этому пути...

   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
    )
person Martin Smith    schedule 06.05.2010
comment
Подобные встроенные TVF, как правило, работают лучше, чем скалярные UDF, поскольку оптимизатор выполняет свою работу лучше. Типичное использование: SELECT t.*, products.qty FROM t OUTER APPLY [dbo].[products](t.product_id) AS products - person Cade Roux; 07.05.2010
comment
Кроме того, если это вообще возможно, не поддавайтесь искушению создать TVF с несколькими операторами — их нельзя оптимизировать так же, как встроенные TVF. - person Cade Roux; 07.05.2010