2011-07-21 10 views
3

我正在寻找一种方法来计算可能包含巨大峰值的给定的一组值的有用平均值。 (例如21,54,34,14,20,300,23或1,1,1,1,200,1,100),当使用标准平均值计算时,尖峰可以将事情关掉。用于规范化平均值的T-SQL

我看着使用中位数,但这并没有真正给出所需的结果。

我想在T-SQL中实现这个

任何想法?

+0

如果你不想要尖峰,那么你需要考虑使用标准偏差。 –

回答

1

这样你就可以拿走计算结果之前的最高和最低的25%。

declare @t table (col1 int) 

insert @t 
select 21 union all 
select 54 union all 
select 34 union all 
select 14 union all 
select 20 union all 
select 300 union all 
select 23 union all 
select 1 union all 
select 1 union all 
select 1 union all 
select 1 union all 
select 200 union all 
select 1 union all 
select 100 


select avg(col1) from (
select top 67 percent col1 from (
select top 75 percent col1 from @t order by col1 
) a order by col1 desc) b 
0
  1. 通过对数规则创建GROUP BY非代表基团(例如数之间的差异不超过10倍或日志的任何其他碱)
  2. 创建过滤(使用HAVING)(例如小于3)
0

这样做的危险之处在于,您无法确定所有这些尖峰都是微不足道的,值得舍弃。一个人的噪音是另一个人的黑天鹅。

如果您担心大数值会不必要地歪曲您的数据视图,那么最好使用像中值这样的对异常值不敏感的度量。计算比平均值更难,但它会给你一个中心性的测量,而不是由尖峰引起的。

1

使用中值滤波:

SELECT AVG(value) 
FROM (
     SELECT TOP 1 value AS median 
     FROM (
       SELECT TOP 50 PERCENT value 
       FROM mytable 
       ORDER BY 
         value 
       ) q 
     ORDER BY 
       value DESC 
     ) q 
JOIN mytable m 
ON  ABS(LOG10(value) - LOG10(median)) <= @filter_level 
+0

从我+1,很好的解决方案 –

+0

错误时处理零或负值 – MakkyNZ

0

您可以考虑使用OVER/PARTITION BY之类的窗口函数。这将允许您在特定的行组(例如按名称,日期或小时)内微调排除项。在这个例子中,我借用示例t-clausen.dk中的行,并通过添加名称来展开,以便我们可以演示窗口。

 
-- Set boundaries, like the TOP PERCENT used in the afore mentioned example 
DECLARE @UBOUND FLOAT, @LBOUND FLOAT

SET @UBOUND = 0.8 --(80%) SET @LBOUND = 0.2 --(20%)

--Build a CTE table ;WITH tb_example AS ( select [Val]=21,[fname]='Bill' union all select 54,'Tom' union all select 34,'Tom' union all select 14,'Bill' union all select 20,'Bill' union all select 300,'Tom' union all select 23,'Bill' union all select 1,'Tom' union all select 1,'Tom' union all select 1,'Bill' union all select 1,'Tom' union all select 200,'Bill' union all select 1,'Tom' union all select 12,'Tom' union all select 8,'Tom' union all select 11,'Bill' union all select 100,'Bill' )

--Outer query applies criteria of your choice to remove spikes SELECT fname,AVG(Val) FROM ( -- Inner query applies windowed aggregate values for outer query processing SELECT * ,ROW_NUMBER() OVER (PARTITION BY fname order by Val) RowNum ,COUNT(*) OVER (PARTITION BY fname) RowCnt ,MAX(Val) OVER (PARTITION BY fname) MaxVal ,MIN(Val) OVER (PARTITION BY fname) MinVal FROM tb_example ) TB WHERE -- You can use the bounds to eliminate the top and bottom 20% RowNum BETWEEN (RowCnt*@LBOUND) and (RowCnt*@UBOUND) -- Limits window -- Or you may chose to simply eliminate the Max and MIN values OR (Val > MinVal AND Val < MaxVal) -- Removes Lowest and Highest values GROUP BY fname

在这种情况下,我同时使用标准和AVG val by fname。但天空是你选择用这种技术减轻峰值的限制。