sql server函数计算中位数

时间:2013-07-22 18:37:39

标签: sql-server

我正在尝试创建函数来计算3个值的中位数,但得到的错误很少 - “函数中的Stmt无法将数据返回给客户端”

CREATE FUNCTION median(@value1 float,@value2 float,@value3 float)
RETURNS float
AS
BEGIN
    DECLARE @ret float;
    DECLARE @CNT int = 3;

    select cast(avg(tb1.val*1.0) as float) as @ret
    from 
       (select 
          val, ROW_NUMBER() over (order by val) as rid 
        from 
            (select @value1 val
         union 
             select @value2 val
         union
             select @value3 val) TB1
        where tb1.rid in ((@cnt + 1) / 2, (@cnt + 2) / 2)

    return @ret;
end;

3 个答案:

答案 0 :(得分:4)

你的语法错了。您在函数中间选择结果集,而不是将值赋给局部变量,因此错误。试试这个:

...
set @ret = (select cast(avg(tb1.val*1.0) as float) 
    from (select val, ROW_NUMBER() over (order by val) as rid from 
            (select @value1 val
            union 
            select @value2 val
            union
            select @value3 val) TB1
    where tb1.rid in ((@cnt+1)/2,(@cnt+2)/2)
    )
...

答案 1 :(得分:0)

CREATE FUNCTION medianx(@value1 float,@value2 float,@value3 float)
RETURNS numeric(10,2)
AS
    BEGIN
        DECLARE @ret float;
        DECLARE @CNT int = 3;
        select @ret=cast(avg(tb1.val*1.0) as numeric(10,2)) 
            from (select val, ROW_NUMBER() over (order by val) as rid from 
                (select @value1 val
                union 
                select @value2 val
                union
                select @value3 val) TB1) TB1
        where tb1.rid in ((@cnt+1)/2,(@cnt+2)/2)



    RETURN @ret
    end;

答案 2 :(得分:0)

在这种情况下,当一个或多个输入参数可能具有NULL值时:

create function median(@v1 float, @v2 float, @v3 float)
returns float
as
begin
    declare @median float;

    ;with D(V, N) as (
        select V, row_number() over (order by V)
        from (values (@v1), (@v2), (@v3)) T(V)
        where V is not NULL)
    ,C(Cnt) as (select count(1) from D)
    select @median = (
        select avg(V) as Median
        from C, D
        where C.Cnt % 2 = 1 and N = C.Cnt/2 + 1
            or C.Cnt % 2 = 0 and N in (C.Cnt/2, C.Cnt/2 + 1))

    return @median;
end

上面的函数可以用更一般的形式编写,允许将超过三个值的集合作为表参数传递:

create type FloatData as table (Value float)
GO
create function median(@data as FloatData readonly)
returns float
as
begin
    declare @median float;

    ;with D(V, N) as (
        select Value, row_number() over (order by Value)
        from @data
        where Value is not NULL)
    ,C(Cnt) as (select count(1) from D)
    select @median = (
        select avg(V) as Median
        from C, D
        where C.Cnt % 2 = 1 and N = C.Cnt/2 + 1
            or C.Cnt % 2 = 0 and N in (C.Cnt/2, C.Cnt/2 + 1))

    return @median;
end
GO