在SQL Server 2008中需要有关标量值函数的帮助

时间:2009-12-27 22:30:00

标签: sql sql-server sql-server-2005 sql-server-2008 user-defined-functions

我需要这个标量值函数的帮助。

我想要做的是在max(Value) AS MaxValue行返回我在MaxValue中获得的值。

查询有效,只有ItemIdListPropertyId存在时才会返回1个值,但我无法创建它的函数。

CREATE FUNCTION GetLpivMax 
(
    -- Add the parameters for the function here
    @ItemId int,
    @ListPropertyId int
)
RETURNS int
AS
BEGIN
  DECLARE @output INT;
  WITH U AS (
    SELECT i.Id AS ItemId,
           lpiv.Value,
           lp.Id AS ListPropertyId
      FROM ListPropertyItemValues lpiv
      JOIN ListPropertyItems lpi ON lpi lpi.Id = lpiv.ListPropertyItemId 
      JOIN ListProperties lp ON lp.Id = lpi.ListPropertyId
      JOIN Items i ON i.Id = lpiv.ItemId)
    SELECT @output = MAX(u.value)
      FROM U u
     WHERE u.listpropertyid = @ListPropertyId 
       AND u.itemid = @ItemId
  GROUP BY u.listpropertyid, u.itemid

  RETURN @output
END
GO

4 个答案:

答案 0 :(得分:3)

我提出了你的问题,但我不喜欢任何答案。您应该将代码更改为内联表值函数。这段代码每次都会被认为是程序性的,而且它只是一个查询。

我在http://msmvps.com/blogs/robfarley/archive/2009/12/05/dangers-of-begin-and-end.aspx写了这篇文章,但我会很快解释你应该做些什么:

CREATE FUNCTION GetLpivMax  
( 
    -- Add the parameters for the function here 
    @ItemId int, 
    @ListPropertyId int 
) 
RETURNS TABLE AS 
RETURN (
SELECT MAX(lpiv.Value) as LpivMax
    FROM ListPropertyItemValues lpiv 
    JOIN ListPropertyItems lpi ON lpi.Id = lpiv.ListPropertyItemId  
    JOIN ListProperties lp ON lp.Id = lpi.ListPropertyId 
    JOIN Items i ON i.Id = lpiv.ItemId 
   WHERE lp.id = @ListPropertyId  
     AND i.id = @ItemId 
GROUP BY lp.id, i.id 
);

现在使用它:

SELECT ip.*, m.LpivMax
FROM ItemsAndProperties ip
CROSS APPLY
dbo.GetLpivMax(ip.ItemID, ip.ListPropertyID) m
;

如果您不想从数据集中删除行,则可以使用OUTER APPLY。如果不引用它们,可以添加将被完全忽略的额外聚合。但最重要的是,查询优化器会简化您的查询,因此如果它可以避免做大部分工作,那么它就会。

希望这会有所帮助......

答案 1 :(得分:2)

使用:

DECLARE @output INT

BEGIN
  WITH U AS (
    SELECT i.Id AS ItemId,
           lpiv.Value,
           lp.Id AS ListPropertyId
      FROM ListPropertyItemValues lpiv
      JOIN ListPropertyItems lpi ON lpi.Id = lpiv.ListPropertyItemId 
      JOIN ListProperties lp ON lp.Id = lpi.ListPropertyId
      JOIN Items i ON i.Id = lpiv.ItemId)
    SELECT @output = MAX(u.value)
      FROM U u
     WHERE u.listpropertyid = @ListPropertyId 
       AND u.itemid = @ItemId
  GROUP BY u.listpropertyid, u.itemid

  RETURN @output
END

SELECT @output = MAX(u.value)将值赋给@output变量,然后您需要使用RETURN语法返回它。另一种方法是根据您的需要设置输出参数。

我还将您的JOIN语法从ANSI-89转换为ANSI-99。它具有相同的性能,但比旧语法更好地适应LEFT JOIN,并且在其他数据库上得到广泛支持(如果有需要,可以使它更具可移植性)。

另外,试试:

  SELECT @output = MAX(lpiv.Value)
    FROM ListPropertyItemValues lpiv
    JOIN ListPropertyItems lpi ON lpi.Id = lpiv.ListPropertyItemId 
    JOIN ListProperties lp ON lp.Id = lpi.ListPropertyId
    JOIN Items i ON i.Id = lpiv.ItemId
   WHERE lp.id = @ListPropertyId 
     AND i.id = @ItemId
GROUP BY lp.id, i.id

我认为你不需要CTE ......

答案 2 :(得分:0)

将这些行添加到您的代码中它应该有效:

将其添加到开头(刚好在BEGIN之后)

DECLARE @output int

将此添加到结尾(就在END之前)

RETURN @output

像这样把它们放在一起:

CREATE FUNCTION GetLpivMax 
(
    -- Add the parameters for the function here
    @ItemId int,
    @ListPropertyId int
)
RETURNS int
AS
BEGIN

  DECLARE @output INT;

  WITH U AS (
    SELECT i.Id AS ItemId,
           lpiv.Value,
           lp.Id AS ListPropertyId
      FROM ListPropertyItemValues lpiv
      JOIN ListPropertyItems lpi ON lpi lpi.Id = lpiv.ListPropertyItemId 
      JOIN ListProperties lp ON lp.Id = lpi.ListPropertyId
      JOIN Items i ON i.Id = lpiv.ItemId)

    SELECT @output = MAX(u.value)
      FROM U u
     WHERE u.listpropertyid = @ListPropertyId 
       AND u.itemid = @ItemId
  GROUP BY u.listpropertyid, u.itemid

  RETURN @output
END
GO

答案 3 :(得分:0)

SCALAR VALUED FUNCTION EXAMPLE BY RAJESH

CREATE FUNCTION GETMYDATE(@YEAR INT)
RETURNS DATETIME 
AS
BEGIN
    DECLARE @DATE DATETIME
    IF @YEAR>2000
        SET @DATE=GETDATE()
    ELSE
        SET @DATE=NULL

    RETURN @DATE
END