繁体   English   中英

MySQL 选择结果使用 AVG 和 STD 条件排除异常值

[英]MySQL Select Results Excluding Outliers Using AVG and STD Conditions

我正在尝试编写一个查询,从结果集的平均值中排除超过 6 个标准差的值。 我希望这可以通过子查询优雅地完成,但我无处可去,在我读过的每个类似情况下,目标似乎都有些不同。 我的结果集似乎仅限于一行,我猜是由于调用了聚合函数。 从概念上讲,这就是我所追求的:

SELECT t.Result FROM
  (SELECT Result, AVG(Result) avgr, STD(Result) stdr
   FROM myTable WHERE myField=myCondition limit=75) as t
WHERE t.Result BETWEEN (t.avgr-6*t.stdr) AND (t.avgr+6*t.stdr)

我可以通过用它自己的 select 语句替换 STD 或 AVG 值(即 t.avgr)的每次使用来使其工作:

(SELECT AVG(Result) FROM myTable WHERE myField=myCondition limit=75) 

然而,这似乎比我预期的更混乱(我有一些条件)。 起初我认为指定一个 HAVING 子句是必要的,但随着我了解的更多,它似乎并不是我所追求的。 我很亲近吗? 是否有一些时髦的方法来访问聚合函数的值以在条件中使用(无需返回聚合值)?

是的,您的子查询是没有GROUP BY子句的聚合查询,因此其结果是单行。 当您从中选择时,您不能获得多于​​一行。 此外,它是一个 MySQL 扩展,您可以将Result字段包含在子查询的选择列表中,因为它既不是分组列也不是组的聚合函数(那么在这种情况下它甚至意味着什么,除非可能,所有相关的列值都相同?)。

你应该能够做这样的事情来计算一次平均值和标准偏差,而不是每个结果:

SELECT t.Result FROM
  myTable AS t
  CROSS JOIN (
    SELECT AVG(Result) avgr, STD(Result) stdr
    FROM myTable
    WHERE myField = myCondition
  ) AS stats
WHERE 
  t.myField = myCondition
  AND t.Result BETWEEN (stats.avgr-6*stats.stdr) AND (stats.avgr+6*stats.stdr)
LIMIT 75

请注意,您需要注意统计数据是在您从中选择的同一组行上计算的,因此myField = myCondition谓词重复,而且仅将LIMIT子句删除到外部查询。

您可以向聚合子查询添加更多统计信息,前提是它们都是在同一组行上计算的,或者您可以通过单独的子查询加入在不同行上计算的其他统计信息。 请确保您的所有统计子查询都只返回一行,否则您将获得重复(或没有)结果。

我创建了一个 UDF,它不完全按照您要求的方式计算(它丢弃了顶部和底部的结果的百分比,而不是使用 std),但无论如何它可能对您(或其他人)有用,匹配此处引用的 Excel 函数https://support.office.com/en-us/article/trimmean-function-d90c9878-a119-4746-88fa-63d988f511d3

https://github.com/StirlingMarketingGroup/mysql-trimmean

用法

`trimmean` ( `NumberColumn`, double `Percent` [, integer `Decimals` = 4 ] )
  • `NumberColumn`

    • 要修剪和平均的值列。
  • `Percent`

    • 要从计算中排除的数据点的分数。 例如,如果百分比 = 0.2,则从 20 个点 (20 x 0.2) 的数据集中修剪 4 个点:2 个从顶部开始,2 个从底部开始。
  • `Decimals`

    • (可选)要输出的小数位数。 默认值为 4。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM