LeetCode:Database 16.给定数字的频率查询中位数

要求:请编写一个查询来查找所有数字的中位数并将结果命名为 median 。

Numbers 表:

+----------+-------------+
|  Number  |  Frequency  |
+----------+-------------|
|  0       |  7          |
|  1       |  1          |
|  2       |  3          |
|  3       |  1          |
+----------+-------------+
Numbers 表保存数字的值及其频率。

Result Table:

+--------+
| median |
+--------|
| 0.0000 |
+--------+
在此表中,数字为 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3,所以中位数是 (0 + 0) / 2 = 0。

分析:
1.中位数所在序号无论正序或是逆序都大于等于总个数的2分之一,因此只要使用sum() over()窗口聚合函数,求出正序和逆序的frequency的累加和与总个数的2分之一比较即可

SQL语句:

#1.方法1
select avg(number) as median
from
(select number,
sum(frequency) over(order by number desc ) a1,
sum(frequency) over(order by number asc) d1,
sum(frequency) over() as s1
from numbers)a
where a1 >= s1/2 and d1 >=s1/2;
#2.方法2使用mysql自带的mysql.help_topic表实现一行转多行,根据id/2,id/2+1,id/2+0.5得到number对应的id求出number的均值,(不过在leecode中无法使用)
WITH numbers02 AS (
SELECT  @id:=@id+1 AS id ,number
FROM
(SELECT @id:=0)e
,(
SELECT b.number,
SUBSTRING_INDEX(
SUBSTRING_INDEX(f2,',',c.help_topic_id+1),',',-1)AS f3
FROM 
(		
SELECT number ,SUBSTRING_INDEX(f1,',',frequency) AS f2
FROM
(SELECT number,frequency,REPEAT(REPLACE(frequency,frequency,'1,'),frequency)AS
f1 FROM numbers)a)b
JOIN mysql.help_topic c ON c.help_topic_id<(LENGTH(b.f2)-LENGTH(
REPLACE(b.f2,',',''))+1
))d)

SELECT s/IF(c2=2,2,1) AS median FROM(
SELECT	COUNT(id) AS c2,SUM(number) AS s FROM(
SELECT id,number,COUNT(*) over() AS c1 FROM 
numbers02 )a1
WHERE id IN(c1/2+1,c1/2,c1/2+0.5)
)a2;
#3.方法3,自定义一个表实现id从0自增实现mysql.help_topic表中id的功能,不过需要判断数字出现频率的最大值建表,(超级麻烦,数据过多,不易判断最大频率,在观察leecode的数据库后建的表,成功实现)
WITH numbers02 AS (
SELECT  @id:=@id+1 AS id ,number
FROM
(SELECT @id:=0)e
,(
SELECT b.number,
SUBSTRING_INDEX(
SUBSTRING_INDEX(f2,',',c.id+1),',',-1)AS f3
FROM 
(		
SELECT number ,SUBSTRING_INDEX(f1,',',frequency) AS f2
FROM
(SELECT number,frequency,REPEAT(REPLACE(frequency,frequency,'1,'),frequency)AS
f1 FROM numbers)a)b
JOIN 
(SELECT 0 AS id
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
UNION ALL
SELECT 11
UNION ALL
SELECT 12
UNION ALL
SELECT 13
UNION ALL
SELECT 14
)
c ON  c.id<(LENGTH(b.f2)-LENGTH(
REPLACE(b.f2,',',''))+1
)
ORDER BY number ASC)d )

SELECT s/IF(c2=2,2,1) AS median FROM(
SELECT	COUNT(id) AS c2,SUM(number) AS s FROM(
SELECT id,number,COUNT(*) over() AS c1 FROM 
numbers02 )a1
WHERE id IN(c1/2+1,c1/2,c1/2+0.5)
)a2;
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值