MySQL - 选择列表的平均值但忽略最大值和最小值

Posted

技术标签:

【中文标题】MySQL - 选择列表的平均值但忽略最大值和最小值【英文标题】:MySQL - select avg of list but ignore max and min value 【发布时间】:2019-08-07 12:43:49 【问题描述】:

我的数据库中有一个值列表。

k v
1 5000
1 100
1 120
1 3
2 5000
2 100
2 120
2 4
3 10000
3 120
3 100
3 4
4 10
4 120
4 110
4 5000

我想计算每个 k 的平均值,但我需要忽略每个 k 的 v 的最高和最低值。 (去除尖刺)

select avg(v) from table where v > min(v) and v < max(v) group by k

导致:

“组函数的无效使用”

我认为这是一项非常常见的任务,但我无法从文档中找到任何想法。

感谢您的建议。

【问题讨论】:

你的主键是什么?期望的结果应该是什么样的? 这不是你应该避免尖峰的方式 避免尖峰的方法是? 对于每个k,您的样本显示v 的两个值。如果你想忽略 v 的最小值和最大值,你将没有任何东西可以计算平均值。 (或者也许我不明白你在寻找什么,你可以展示一个预期的结果。) 当然我在数据库中有更多的值。我已经更改了示例以使其清楚 【参考方案1】:

一种无需担心v 是否存在重复的最小值和最大值(假设您只想忽略其中一个)的方法是将平均值作为SUM(v)/COUNT(v),但减去最小值和最大值计算值:

SELECT k, (SUM(v) - MAX(v) - MIN(v)) / (COUNT(v) - 2) AS average
FROM data
GROUP BY k

输出:

k   average
1   110
2   110
3   110
4   115

Demo on dbfiddle

【讨论】:

每个k的平均值 @MikeNathas 抱歉 - 感谢您指出这一点,我在问题中错过了它。【参考方案2】:
select avg(v) , k 
from table 
group by k  
    having k <> min (v) and k<> max (v)

【讨论】:

【参考方案3】:

首先获取每个k 的最小值和最大值v,然后将left join 表格获取到结果,以便获得不匹配行的平均值:

select
  t.k, avg(t.v) average
from tablename t left join (
  select k, min(v) minv, max(v) maxv
  from tablename
  group by k
) g on g.k = t.k and t.v in (g.minv, g.maxv)
where g.k is null
group by t.k

请参阅demo。 结果:

| k   | average |
| --- | ------- |
| 1   | 110     |
| 2   | 110     |
| 3   | 110     |
| 4   | 115     |

【讨论】:

【参考方案4】:

链接: Demo

select t1.k, avg(t1.v) average
from numbers t1 left join (
  select k, min(v) minv, max(v) maxv
  from numbers 
  group by k
) t2 on t2.k = t1.k and t1.v in (t2.minv, t2.maxv)
where t2.k is null
group by t1.k

【讨论】:

以上是关于MySQL - 选择列表的平均值但忽略最大值和最小值的主要内容,如果未能解决你的问题,请参考以下文章

列表中的 Python 平均值、最大值、最小值

查找整数数组的平均值

python求一组数组最大值,最小值,平均值

05_MySQL常见函数_分组函数

SqlServer函数的聚合函数

MySQL的聚合函数