2

我有一张带选票的桌子。投票只有数字(没有文字,没有是/否等)。

原始数据示例

id   | question_id | vote
1    | 63          | 80
2    | 63          | 13
3    | 63          | 992
...
100  | 63          | 900000
101  | 63          | 5

我想获得特定问题的平均值,但忽略最高和最低 X% 的选票(例如:忽略 5% - 所以每 100 票我将平均只有 90 票) - 不是按 id 而是按最大值和投票数的最小值。

在上表中,平均值中不会考虑 900000 和 5(假设它们是该问题的最高和最低票数)

4

2 回答 2

7

该查询应该可以完成这项工作(参见 SQL Fiddle 上的示例)

SELECT AVG(vote) FROM
(
  SELECT vote, @r:=@r+1 AS rownum
  FROM votes, (SELECT @r:=0) x
  WHERE question_id = 63
  ORDER BY vote
) x
WHERE rownum > @r * .05
  AND rownum <= @r * .95
;

子查询使用一个变量为每条记录分配一个行号,外部查询删除最低和最高的数字。

于 2013-01-01T10:36:37.790 回答
0

这是您可能使用的基本思想:

SELECT AVG(vote) AS average
FROM tbl o 
WHERE question_id=?
AND (
   SELECT count(*)
   FROM tbl i
   WHERE o.question_id = i.question_id
   AND o.vote < i.vote 
)/(
   SELECT count(*)
   FROM tbl inner
   WHERE o.question_id = i.question_id
) IS BETWEEN 0.05 AND 0.95
GROUP BY question_id

直观上看,复杂度是投票数的二次方(除非查询执行器可以优化第一个子查询;第二个更容易优化)

其他一些数据库引擎有一个行号作为您可以在查询中使用的值。这可能会帮助您实现线性复杂性。

您也可以通过多个查询来实现线性复杂性:

  1. 查询带有问题 ID 的总行数。
  2. 按排序顺序计算 5% 和 95% 边界的位置。
  3. 用 查询与边界对应的投票LIMIT。您可以并行运行两个查询,这要归功于UNION.
  4. 查询知道票数最高和最低票的平均票数。

如果有重复投票,您可能需要用向量替换vote列以vote, ID找到边界(这适用于两个查询)。基本思想是一样的。

于 2013-01-01T10:36:49.990 回答