2016-08-15 133 views
2

这是我的数据是什么样子:如何获得每组平均,并找出异常值在SQL

id | value | group 
------------------ 
1 | 4  | abc 
2 | 8  | def 
3 | 100 | abc 
4 | 8  | ghi 
5 | 7  | abc 
6 | 10 | ghi 

我需要为每个组计算出的平均值,其中的异常值(用于如ID = 3组= abc)被排除在外。然后显示平均值旁边的ouliers。对于上述数据,我希望这样的事情的结果:

group = 'abc' 
average = '5.5' 
outlier = '100' 
+1

根据什么给你定义了一个异常? –

+0

你如何定义异常值一个值超过平均值的一个标准偏差? –

+0

是的,异常值大于平均值的一个标准偏差。 – user5495762

回答

2

一种方法创建一个包含每个组的统计子查询所需要的价值(平均值和标准偏差),然后将其加回到原始表格中,以确定哪些记录是异常值,为哪个组。

SELECT t1.id, 
     t1.group AS `group`, 
     t2.valAvg AS average, 
     t1.value AS outlier 
FROM yourTable t1 
INNER JOIN 
(
    SELECT `group`, AVG(value) AS valAvg, STDDEV(value) AS valStd 
    FROM yourTable 
    GROUP BY `group` 
) t2 
    ON t1.group = t2.group 
WHERE ABS(t1.value - t2.valAvg) > t2.valStd -- any record whose value is MORE 
               -- than one standard deviation from 
               -- the mean is an outlier 

更新:

看来,出于某种原因,你的value列是实际varchar而不是数字类型。这意味着你将无法对其进行任何数学运算。所以第一,列转换为整数通过:

ALTER TABLE yourTable MODIFY value INTEGER; 

如果你只是想离群这是更大比普通然后使用以下WHERE条款:

WHERE t1.value - t2.valAvg > t2.valStd 
+0

当我运行您的查询时,我收到此错误:将数据类型varchar转换为数字时出错。 – user5495762

+0

将'value'列转换为数字类型。 –

+0

如果我展开我的表的列文件夹,它将values列显示为'(numeric(18,2),null)' – user5495762

0

您可以排除不使用子查询

select `group`, avg/value) from my_table 
where (group, value) not in (select `group`, max(value) 
           from my_table 
           group by `group`) 
from my_table 
group by `group`