我想计算 Median此简单 xy_table
的 子组 中 y
的:
x | y --groups--> gid | x | y --medians--> gid | x | y
------- ------------- -------------
0.1 | 4 0.0 | 0.1 | 4 0.0 | 0.1 | 4
0.2 | 3 0.0 | 0.2 | 3 | |
0.7 | 5 1.0 | 0.7 | 5 1.0 | 0.7 | 5
1.5 | 1 2.0 | 1.5 | 1 | |
1.9 | 6 2.0 | 1.9 | 6 | |
2.1 | 5 2.0 | 2.1 | 5 2.0 | 2.1 | 5
2.7 | 1 3.0 | 2.7 | 1 3.0 | 2.7 | 1
在此示例中,每个 x
都是唯一的,并且表格已按 x
排序。
我现在想要 GROUP BY round(x)
并获取每个组中包含 y
中位数的元组。
我已经可以用这个排名查询计算整个表的中位数:
SELECT a.x, a.y FROM xy_table a,xy_table b
WHERE a.y >= b.y
GROUP BY a.x, a.y
HAVING count(*) = (SELECT round((count(*)+1)/2) FROM xy_table)
输出:0.1, 4.0
但我还没有成功编写查询来计算子组的中位数。
注意:我没有可用的median()
聚合函数。也请不要提出具有特殊 PARTITION
、RANK
或 QUANTILE
语句的解决方案(如在类似但供应商特定的 SO questions 中找到的)。我需要纯 SQL(即与没有 median()
函数的 SQLite 兼容)
最佳答案
我建议用您的编程语言进行计算:
for each group:
for each record_in_group:
append y to array
median of array
但如果你被 SQLite 困住了,你可以按 y
对每个组进行排序,然后像这样选择中间的记录 http://sqlfiddle.com/#!5/d4c68/55/0 :
更新:对于偶数 nr,只有更大的“中值”值才是重要的。行数,因此不需要 avg()
:
select groups.gid,
ids.y median
from (
-- get middle row number in each group (bigger number if even nr. of rows)
-- note the integer divisions and modulo operator
select round(x) gid,
count(*) / 2 + 1 mid_row_right
from xy_table
group by round(x)
) groups
join (
-- for each record get equivalent of
-- row_number() over(partition by gid order by y)
select round(a.x) gid,
a.x,
a.y,
count(*) rownr_by_y
from xy_table a
left join xy_table b
on round(a.x) = round (b.x)
and a.y >= b.y
group by a.x
) ids on ids.gid = groups.gid
where ids.rownr_by_y = groups.mid_row_right
关于用于计算子组中的排名和中位数的 SQL 排名查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15946580/