用Mysql计算中位数

时间:2011-03-23 05:19:30

标签: mysql statistics median

我在计算值列表的中位数时遇到问题,而不是平均值。

我找到了这篇文章 Simple way to calculate median with MySQL

它引用了以下我不理解的查询。

从数据x,数据y中选择x.val GROUP BY x.val 和(SIGN(1-SIGN(y.val-x.val)))=(COUNT(*)+ 1)/ 2

如果我有时间列并且我想计算中值,那么x和y列是指什么?

7 个答案:

答案 0 :(得分:10)

我提出了一个更快的方法。

获取行数:

SELECT CEIL(COUNT(*)/2) FROM data;

然后在已排序的子查询中取中间值:

SELECT max(val) FROM (SELECT val FROM data ORDER BY val limit @middlevalue) x;

我用随机数的5x10e6数据集进行了测试,发现中位数不到10秒。

通过将COUNT(*)/2替换为COUNT(*)*n,其中n为百分位数(中位数为0.5,第75百分位数为.75等),可以找到任意百分位数。

答案 1 :(得分:2)

val是您的时间列,xy是对数据表的两个引用(您可以编写data AS x, data AS y)。

编辑: 为避免计算两次总和,可以存储中间结果。

CREATE TEMPORARY TABLE average_user_total_time 
      (SELECT SUM(time) AS time_taken 
            FROM scores 
            WHERE created_at >= '2010-10-10' 
                    and created_at <= '2010-11-11' 
            GROUP BY user_id);

然后,您可以计算命名表中这些值的中位数。

编辑:临时表won't work。您可以尝试使用具有“MEMORY”表类型的常规表。或者只是让您的子查询在查询中计算两次中值的值。除此之外,我没有看到另一种解决方案。这并不意味着没有更好的方法,也许其他人会有想法。

答案 2 :(得分:1)

首先尝试了解中位数是什么:它是排序值列表中的中间值。

一旦你理解了这一点,这个方法就是两个步骤:

  1. 按任意顺序对值进行排序
  2. 选择中间值(如果不是奇数个值,则选择两个中间值的平均值)
  3. 示例:

    Median of 0 1 3 7 9 10: 5 (because (7+3)/2=5)
    Median of 0 1 3 7 9 10 11: 7 (because 7 is the middle value)
    

    因此,要对日期进行排序,您需要一个数值;你可以得到他们的时间戳(从纪元开始经过秒)并使用中位数的定义。

答案 3 :(得分:1)

使用group_concat

查找mysql的中位数

<强>查询:

SELECT
    IF(count%2=1,
       SUBSTRING_INDEX(substring_index(data_str,",",pos),",",-1),
       (SUBSTRING_INDEX(substring_index(data_str,",",pos),",",-1) 
         + SUBSTRING_INDEX(substring_index(data_str,",",pos+1),",",-1))/2) 
    as median 
FROM (SELECT group_concat(val order by val) data_str,
      CEILING(count(*)/2) pos,
      count(*) as count from data)temp;

<强>解释

使用内部group_concat函数

的顺序完成排序

识别位置(pos)和元素总数(计数)。 CEILING识别位置有助于我们在以下步骤中使用substring_index函数。

根据计数,确定偶数或奇数个值。

  • 奇数值:使用substring_index直接选择属于pos的元素。
  • 偶数值:找到属于pos和pos + 1的元素,然后加上它们除以2得到中位数。

最后计算中位数。

答案 4 :(得分:1)

我和我的朋友发现...的最简单方法!

SELECT count(*) INTO @c from station;
select ROUND((@c+1)/2) into @final; 
SELECT round(lat_n,4) from station a where @final-1=(select count(lat_n) from station b where b.lat_n > a.lat_n);

答案 5 :(得分:0)

如果您的表格R包含名为A的列,并且您希望中位数为,则可以执行以下操作:

SELECT A FROM R R1
WHERE ( SELECT COUNT(A) FROM R R2 WHERE R2.A < R1.A ) = ( SELECT COUNT(A) FROM R R3 WHERE R3.A > R1.A )

注意:这仅在A中没有重复值时才有效。此外,不允许使用空值。

答案 6 :(得分:0)

这是一个易于理解的解决方案。只需根据您的要求替换 Your_Column Your_Table

SET @r = 0;

SELECT AVG(Your_Column)
FROM (SELECT (@r := @r + 1) AS r, Your_Column FROM Your_Table ORDER BY Your_Column) Temp
WHERE
    r = (SELECT CEIL(COUNT(*) / 2) FROM Your_Table) OR
    r = (SELECT FLOOR((COUNT(*) / 2) + 1) FROM Your_Table)

最初来自this thread