В MySQL есть какой-то способ рассчитать среднее значение со списком чисел?

0

Я хотел бы сделать что-то вроде следующего:

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;

Если бы я предположил, что это было бы возможно с другими функциями, такими как variance() и другими.

Редактировать: эта идея из любопытства не является реальной проблемой, которую мне нужно решить.

  • 0
    MySQL не является языком программирования общего назначения, поэтому он предпочитает вещи, выраженные в виде таблиц, как у вас там.
  • 2
    select (1+2+3)/3
Показать ещё 4 комментария
Теги:
select
function
average

3 ответа

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

Смотрите живую рабочую демонстрацию здесь.

Разница может быть намного сложнее, но я надеюсь, что вы получите эту идею.

  • 0
    Не читал код, полагаю, он работает. Похоже, это будет путь ...
0

Вы используете неправильные инструменты для решения своей проблемы.

Если вы хотите рассчитать дисперсию списка, используйте какой-то язык сценариев, будь то Php, Python и т.д. Если вы хотите сначала сохранить данные и только потом вычислить дисперсию, конечно, используйте что-то вроде MySql.

0

AVG может иметь только один аргумент. Вам нужно сделать SELECT AVG(num) FROM nums

Вы также можете сделать SELECT SUM(num)/COUNT(num) FROM nums

Просто знайте, поскольку вы делите с помощью ints, что это будет неточно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню