LeetCode:Database 16.给定数字的频率查询中位数
Posted Xiao Miao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
以上是关于LeetCode:Database 16.给定数字的频率查询中位数的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode:Database 77.找到连续区间的开始和结束数字