示例表:
age | fruit | number_bought |
20 | apple | 3000000 |
20 | apple | 20 |
20 | apple | 60 |
20 | apple | 30 |
20 | apple | 50 |
20 | apple | 4 |
20 | banana| 40 |
30 | grape | 400 |
30 | grape | 450 |
30 | grape | 500 |
简单地列出一个特定年龄的人在该年龄购买了多少特定水果。
现在,我需要按“最受欢迎的水果”对这张表进行排序,并按年龄和水果分组。
这是棘手的部分,我想使用 MEDIAN 来计算受欢迎程度,而不仅仅是平均数。因为有些人可能很不正常(他可能是推销员),比如上面示例中的 3000000,而“平均 20 岁”的购买量要少得多,正如您从示例中看到的那样。
上表按流行度中位数排序应该是这样的:
age | fruit | median |
30 | grape | 450 |
20 | apple | 40 |
20 | banana| 40 |
现在,如果我简单地使用“平均”计算,20,苹果就会赢得人气,仅仅因为一个推销员。这就是我想使用中位数的原因。
最佳答案
当项目数量为偶数时(例如,测试数据中有 apple),常见的中值查询似乎很困难。
简单的方法是:-
SELECT y.age, x.fruit, AVG(x.number_bought) AS number_bought
from data x
INNER JOIN data y
ON x.age = y.age
AND x.fruit = y.fruit
GROUP BY y.age, x.fruit, x.number_bought
HAVING SUM(SIGN(1-SIGN(y.number_bought-x.number_bought))) = FLOOR((COUNT(*)+1)/2)
ORDER BY number_bought DESC;
这并不严格准确,因为它只是取中间一条之前的一条(即,6 条记录的中位数将是位置 3.5 的一条 - 这仅使用 FLOOR 并获得记录号 3)。
可能稍微更准确一点,当有偶数时,这将得到 2 条记录任一侧的平均值
SELECT age, fruit, AVG(number_bought) AS number_bought
FROM
(
SELECT y.age, x.fruit, AVG(x.number_bought) AS number_bought
from data x
INNER JOIN data y
ON x.age = y.age
AND x.fruit = y.fruit
GROUP BY y.age, x.fruit, x.number_bought
HAVING SUM(SIGN(1-SIGN(y.number_bought-x.number_bought))) = FLOOR((COUNT(*)+1)/2)
OR SUM(SIGN(1-SIGN(y.number_bought-x.number_bought))) = CEIL((COUNT(*)+1)/2)
) Sub1
GROUP BY age, fruit
ORDER BY number_bought DESC;
SQL fiddle 在这里:-
关于mysql - MySQL中按中位数的复杂排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23811994/