【问题标题】:How to get average per group and figure out outliers in SQL如何获得每组的平均值并找出 SQL 中的异常值
【发布时间】:2016-12-21 19:20:40
【问题描述】:

这是我的数据的样子:

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'

【问题讨论】:

  • 你认为什么是异常值?
  • 你如何定义异常值,例如与平均值的一个标准差以上的值?
  • 是的,离群值是任何大于平均值的标准差。
  • 可能有多个异常值,我需要在输出中列出每个异常值。

标签: mysql sql statistics aggregate


【解决方案1】:

一种方法创建一个子查询,其中包含每个组的统计信息(平均值和标准差),然后将其连接回原始表以确定哪些记录是异常值,哪些组。

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

【讨论】:

  • 当我运行您的查询时,我收到此错误:将数据类型 varchar 转换为数字时出错。
  • value 列转换为数字类型。
  • 如果我展开表的列文件夹,它会将值列显示为“(数字(18,2),空值)”
  • 那么您应该不会收到此错误。如果没有亲眼看到您的设置,恐怕我无法在此处提供更多见解。
  • 我的代码有错误,在更正后,它现在似乎可以工作了!有没有办法只列出大于或大于平均值而不低于平均值的异常值?另外,我如何显示与这些异常值相关的 ID? -谢谢!
【解决方案2】:

您可以使用子查询排除不需要的值

 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`

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多