在MySQL中,有一些方法可以通过数字列表来计算平均值?

时间:2018-07-26 20:09:31

标签: mysql function select average

我想做以下事情:

SELECT AVG([1,2,3]);

这当然会返回2。我最接近的是以下内容,虽然不理想,但可以放在一行:

drop table nums;
create temporary table nums (num int);
insert into nums(num) values(1),(2),(3);
select avg(num) from nums;

如果有一种方法,我认为使用variant()和其他函数也可以实现这一点。

编辑:这种想法出于好奇,不是我需要解决的真正问题。

3 个答案:

答案 0 :(得分:0)

AVG只能有1个参数。您需要做SELECT AVG(num) FROM nums

您也可以执行SELECT SUM(num) / COUNT(num) FROM nums

就知道了,因为您使用整数进行除法,所以它并不精确。

答案 1 :(得分:0)

您使用了错误的工具来解决问题。

如果要计算列表的方差,请使用某种脚本语言,例如Php,Python等。如果要首先存储,而仅然后计算差异,当然可以使用MySql之类的方法。

答案 2 :(得分:0)

我还认为MySQL可能不是正确的工具(因为您不想存储数字),但问题的答案是:是的,您可以使用MySQL做到这一点无需创建表。

我没有为此找到任何内置功能/结构,但是我想出了以下解决方案。我的想法是创建一个自定义函数,该函数接受带分隔符的字符串中的数字,然后将其拆分并计算数字的平均值。这是使用整数的实现。输入应为num,num,num,依此类推,应以数字结尾(请参见末尾的示例)。

DROP FUNCTION IF EXISTS AVGS;
DELIMITER $$
CREATE FUNCTION AVGS(s LONGTEXT) RETURNS DOUBLE
DETERMINISTIC
BEGIN
    DECLARE sum BIGINT DEFAULT 0;
    DECLARE count BIGINT DEFAULT 0;
    DECLARE pos BIGINT DEFAULT 0;
    DECLARE lft TEXT DEFAULT '';

    -- can we split?
    SET pos = LOCATE(',', s);
    WHILE 0 < pos DO -- while we can split
        SET lft = LEFT(s, pos - 1); -- get the first number
        SET s = SUBSTR(s FROM pos + 1); -- store the rest
        SET sum = sum + CAST(lft AS SIGNED);
        SET count = count + 1;
        SET pos = LOCATE(',', s); -- split again
    END WHILE;

    -- handle last number
    SET sum = sum + CAST(s AS SIGNED);
    SET count = count + 1;

    RETURN sum / count;
END $$
DELIMITER ;

SELECT AVGS("1");     -- prints: 1    
SELECT AVGS("1,2");   -- prints: 1.5
SELECT AVGS("1,2,3"); -- prints: 2

查看正在运行的demo here

方差可能要复杂得多,但我希望您能理解。