查找给定数字频率的中位数

zea*_*ous 0 sql sql-server

想要编写一个 SQL Server 查询来查找给定数字频率的中位数。

桌子:

+----------+-------------+
|  number  |  frequency  |
+----------+-------------|
|  2       |  7          |
|  3       |  1          |
|  5       |  3          |
|  7       |  1          |
+----------+-------------+
Run Code Online (Sandbox Code Playgroud)

在这个表中,数字的2, 2, 2, 2, 2, 2, 2, 3, 5, 5, 5, 7中位数是(2 + 2) / 2 = 2

我使用递归 CTE sqlfiddle创建了以下查询,是否有更好的方法来更高效地编写这个查询?

我的解决方案:

/* recursive CTE to generate numbers with given frequency */

with nums as
(
    select
        number,
        frequency
    from numbers

    union all

    select
        number,
        frequency - 1
    from nums
    where frequency > 1
)

/* find median */

select
    round(avg(number * 1.0), 2) as median
from
(
    select
        number,
        count(*) over () as ttl,
     row_number() over (order by number) as rnk
    from nums
) t
where rnk = (case when ttl%2 != 0 then (ttl/2) else (ttl/2)+1 end)
or rnk = (case when ttl%2 = 0 then (ttl/2)+1 end)
Run Code Online (Sandbox Code Playgroud)

Gor*_*off 6

只需进行累加并取中间值即可。我认为这个逻辑是这样的:

select avg(number)
from (select t.*,
             sum(freq) over (order by number asc) as sum_freq,
             sum(freq) over () as cnt
      from t
     ) t
where cnt <= 2 * sum_freq and
      cnt >= 2 * (sum_freq - freq);
Run Code Online (Sandbox Code Playgroud)

是一个 db<>fiddle。