2013-07-22 121 views
2

我試圖創建函數來計算3個值的中值,但得到一些錯誤 - 「功能中的語句無法數據返回到客戶端」SQL Server函數來計算平均

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; 
+0

哦,男人......我寫了一個在我上一份工作,從來沒有複製代碼。 – SQLMason

回答

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) 
    ) 
... 
+0

謝謝...它的工作... – user1050619

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; 
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