SQL Server中位数函数

时间:2013-10-25 20:48:40

标签: sql-server

CREATE FUNCTION [dbo].[f_Get_Average_Order_Size_Median]
(
      @ITEM char(15)
)
RETURNS decimal(21,6)
AS
BEGIN

SELECT @Median = AVG(1.0 * QTYSHP)
FROM
(
    SELECT o.QTYSHP, rn = ROW_NUMBER() OVER (ORDER BY o.QTYSHP), c.c 
    FROM dbo.tbl AS o 
        WHERE RQDATE >=DATEADD (mm,-6, GETDATE()) 
        AND PRICE != '0' 
        AND SALESMN != 'WB' 
        AND item = @ITEM )  

   +
    SELECT o.QTYSHP, rn = ROW_NUMBER() OVER (ORDER BY o.QTYSHP), c.c
    FROM tbl 
        WHERE RQDATE >=DATEADD (mm,-6, GETDATE()) 
        AND PRICE != '0' 
        AND SALESMN != 'WB' 
        AND item = @ITEM  
   CROSS JOIN (SELECT c = COUNT(*) 
               FROM dbo.tblS) AS c
                   WHERE RQDATE >=DATEADD (mm,-6, GETDATE()) 
                   AND PRICE != '0' 
                   AND SALESMN != 'WB' 
                   AND item = @ITEM
   +  
   (SELECT c = COUNT(*) 
    FROM dbo.tblS) AS c
        WHERE RQDATE >=DATEADD (mm,-6, GETDATE()) 
        AND PRICE != '0' 
        AND SALESMN != 'WB' 
        AND item = @ITEM
   ) AS x
WHERE rn IN ((c + 1)/2, (c + 2)/2);


      @Return = @Median
      BEGIN 

      END
      RETURN @Return

END TRANSACTION...

这是正确的中位函数吗?请纠正我..我正在学习

2 个答案:

答案 0 :(得分:2)

中位数是累积50%值(50%百分位数)的值。所以我认为最简单的方法是:

  1. 计算记录数(假设此计数为'n')
  2. 选择最高n / 2条记录(如果n为偶数,将其四舍五入为下一个整数值),按照包含您要计算中位数的值的列进行排序。阅读本专栏的最大(最后)值。
  3. 我不太熟悉SQL服务器,但在MySQL中,我会这样做:

    set @n = (select count(*) from yourTable);
    set @med = ceil(@n / 2);
    select yourColumn
    from (
        select yourColumn
        from yourTable
        order by yourColumn
        limit @med
    ) as a
    order by yourColumn desc
    limit 1;
    

答案 1 :(得分:0)

对于SQL Server 2005+,您可以尝试此解决方案:

DECLARE @MyTable TABLE
(
    ID INT PRIMARY KEY,
    Value NUMERIC(9,2)
);
INSERT  @MyTable (ID, Value) VALUES (1, 10);
INSERT  @MyTable (ID, Value) VALUES (2, 20);
INSERT  @MyTable (ID, Value) VALUES (3, 30);
INSERT  @MyTable (ID, Value) VALUES (4, 40);

-- Test #1: 4 rows => AVG(20,30)
SELECT  AVG(y.Value) AS Median#1
FROM
(
SELECT  *,
        ROW_NUMBER() OVER(ORDER BY x.ID ASC) AS RowNumASC,
        ROW_NUMBER() OVER(ORDER BY x.ID DESC) AS RowNumDESC
FROM    @MyTable x
) y
WHERE y.RowNumASC = y.RowNumDESC
OR y.RowNumASC + 1 = y.RowNumDESC
OR y.RowNumASC - 1 = y.RowNumDESC;
-- End of Test #1

-- Test #2: 5 rows => AVG(30)
INSERT  @MyTable (ID, Value) VALUES (5, 50);
SELECT  AVG(y.Value) AS Median#2
FROM
(
SELECT  *,
        ROW_NUMBER() OVER(ORDER BY x.ID ASC) AS RowNumASC,
        ROW_NUMBER() OVER(ORDER BY x.ID DESC) AS RowNumDESC
FROM    @MyTable x
) y
WHERE y.RowNumASC = y.RowNumDESC
OR y.RowNumASC + 1 = y.RowNumDESC
OR y.RowNumASC - 1 = y.RowNumDESC;
-- End of Test #2

结果:

Median#1
---------
25.000000

Median#2
---------
30.000000