我有一个非常简单的表,像这样:
CREATE TABLE IF NOT EXISTS LuxLog ( Sensor TINYINT, Lux INT, PRIMARY KEY(Sensor) )
它包含来自不同传感器的数千条日志。
我希望所有传感器都具有Q1和Q3。
我可以对每个数据执行一次查询,但对所有传感器执行一次查询会更好(从一次查询中获取Q1和Q3)
尽管这将是一个相当简单的操作,因为四分位数被广泛使用,并且是频率计算中的主要统计变量之一。事实是,我发现了很多过于复杂的解决方案,而我却希望找到一些简洁明了的东西。
有人可以给我提示吗?
编辑:这是我在网上找到的一段代码,但是对我不起作用:
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX( GROUP_CONCAT( -- 1) make a sorted list of values Lux ORDER BY Lux SEPARATOR ',' ) , ',' -- 2) cut at the comma , 75/100 * COUNT(*) -- at the position beyond the 90% portion ) , ',' -- 3) cut at the comma , -1 -- right after the desired list entry ) AS `75th Percentile` FROM LuxLog WHERE Sensor=12 AND Lux<>0
我得到1作为返回值,而它应该是可以除以10的数字(10,20,30 ..... 1000)
请参阅SqlFiddle:http : //sqlfiddle.com/#!9/accca6/2/6注意:对于sqlfiddle我已经生成了100行,介于1和100之间的每个整数都有一行,但是它是一个随机顺序(完成在Excel中)。
这是代码:
SET @number_of_rows := (SELECT COUNT(*) FROM LuxLog); SET @quartile := (ROUND(@number_of_rows*0.25)); SET @sql_q1 := (CONCAT('(SELECT "Q1" AS quartile_name , Lux, Sensor FROM LuxLog ORDER BY Lux DESC LIMIT 1 OFFSET ', @quartile,')')); SET @sql_q3 := (CONCAT('( SELECT "Q3" AS quartile_name , Lux, Sensor FROM LuxLog ORDER BY Lux ASC LIMIT 1 OFFSET ', @quartile,');')); SET @sql := (CONCAT(@sql_q1,' UNION ',@sql_q3)); PREPARE stmt1 FROM @sql; EXECUTE stmt1;
编辑 :
SET @current_sensor := 101; SET @quartile := (ROUND((SELECT COUNT(*) FROM LuxLog WHERE Sensor = @current_sensor)*0.25)); SET @sql_q1 := (CONCAT('(SELECT "Q1" AS quartile_name , Lux, Sensor FROM LuxLog WHERE Sensor=', @current_sensor,' ORDER BY Lux DESC LIMIT 1 OFFSET ', @quartile,')')); SET @sql_q3 := (CONCAT('( SELECT "Q3" AS quartile_name , Lux, Sensor FROM LuxLog WHERE Sensor=', @current_sensor,' ORDER BY Lux ASC LIMIT 1 OFFSET ', @quartile,');')); SET @sql := (CONCAT(@sql_q1,' UNION ',@sql_q3)); PREPARE stmt1 FROM @sql; EXECUTE stmt1;
基本推理如下:对于四分位数1,我们希望从顶部获得25%,所以我们想知道有多少行,那就是:
SET @number_of_rows := (SELECT COUNT(*) FROM LuxLog);
现在我们知道行数,我们想知道那是行数的25%,它是这一行:
SET @quartile := (ROUND(@number_of_rows*0.25));
然后要找到一个四分位数,我们要按Lux排序LuxLog表,然后获取行号“ @quartile”,为此,我们将OFFSET设置为@quartile表示要从该行开始选择number @quartile,我们说限制1表示我们只想检索一行。那是 :
SET @sql_q1 := (CONCAT('(SELECT "Q1" AS quartile_name , Lux, Sensor FROM LuxLog ORDER BY Lux DESC LIMIT 1 OFFSET ', @quartile,')'));
我们对另一四分位数进行(几乎)相同的操作,但不是从顶部开始(从较高的值到较低的值),而是从底部开始(它解释了ASC)。
但是现在,我们只是将字符串存储在变量@ sql_q1和@ sql_q3中,因此将它们连接起来,我们合并查询的结果,准备查询并执行它。