SQL - 计算中位数而不进行排序

时间:2017-03-04 20:01:16

标签: mysql median

我有一个SQL表,其中包含一列整数值,我希望找到这些值的中位数而不进行任何排序。我首先尝试在表中找到大于和小于每个值的数字:

SELECT DISTINCT d1.v,       
  (SELECT COUNT(d2.v)
   FROM Values d2  
   WHERE d2.v > d1.v
   ) AS greater_than,
   (SELECT COUNT(d2.v)
   FROM Values d2  
   WHERE d2.v < d1.v
   ) AS less_than
FROM Values d1

enter image description here

我不知道该怎么办。我相信我希望上表中greater_thanless_than都等于num_entries / 2的值,但这只适用于具有偶数条目的表。从上面的内容中得到中位数的好方法是什么?

2 个答案:

答案 0 :(得分:2)

你可以这样做:

SELECT (MIN(v)+MAX(v))/2
FROM   (
        SELECT  CASE WHEN
                        LEAST((SELECT COUNT(*) FROM tbl WHERE v <= d1.v),
                              (SELECT COUNT(*) FROM tbl WHERE v >= d1.v))
                           >= (SELECT COUNT(*)/2 FROM tbl) 
                     THEN v
                END as v
        FROM    tbl d1
       ) as sub

内部查询保证在潜在的许多null值中返回1或2个不同的非null值。非null值可能会重复,但通过取最小值和最大值,可以使用这两个值来计算中位数。

注意:不要为你的表Values命名:这是一个保留字。

答案 1 :(得分:0)

查找大于和小于自身数的总数,该总数等于总行数/ 2。

create table med(id integer);
insert into med(id) values(1);
insert into med(id) values(2);
insert into med(id) values(3);
insert into med(id) values(4);
insert into med(id) values(5);
insert into med(id) values(6);

select (MIN(count)+MAX(count))/2 from 
(select case when (select count(*) from 
med A where A.id<B.id)=(select count(*)/2 from med) OR 
(select count(*) from med A where A.id>B.id)=(select count(*)/2 
from med) then cast(B.id as float)end as count from med B) C;

 ?column? 
----------
  3.5
(1 row)

你需要强制转换为浮动,否则你会得到3。