Sql server 标准化平均值的T-SQL

Sql server 标准化平均值的T-SQL,sql-server,algorithm,tsql,data-structures,Sql Server,Algorithm,Tsql,Data Structures,我正在寻找一种方法来计算一组给定值的有用平均值,这些值可能包含巨大的峰值。e、 G21、54、34、14、20、300、23或1、1、1、1、1200、1100使用标准平均值计算时,尖峰可能会脱落 我考虑过使用中位数,但这并没有真正给出期望的结果 我想在T-SQL中实现这一点 有什么想法吗 按对数规则创建分组,例如,数字之间的差值不超过10倍或任何其他对数基数 使用非代表性组创建筛选,例如少于3个 这样做的危险在于,你不能确定所有这些尖峰都是无关紧要的,值得丢弃。一个人的噪音是另一个人的黑天鹅

我正在寻找一种方法来计算一组给定值的有用平均值,这些值可能包含巨大的峰值。e、 G21、54、34、14、20、300、23或1、1、1、1、1200、1100使用标准平均值计算时,尖峰可能会脱落

我考虑过使用中位数,但这并没有真正给出期望的结果

我想在T-SQL中实现这一点

有什么想法吗

按对数规则创建分组,例如,数字之间的差值不超过10倍或任何其他对数基数 使用非代表性组创建筛选,例如少于3个
这样做的危险在于,你不能确定所有这些尖峰都是无关紧要的,值得丢弃。一个人的噪音是另一个人的黑天鹅

若您担心大值不必要地扭曲了数据视图,那个么最好使用对异常值不太敏感的中位数之类的度量。它比平均值更难计算,但它会给你一个中心度的度量,而不受尖峰的影响。

使用中值滤波器:

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

这样,在计算结果之前,您可以去掉最高和最低的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

<>你可以考虑使用Office/Dead的窗口函数。这将允许您微调特定行组中的排除,如按名称、日期或小时。在本例中,我借用了示例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