Я пытаюсь реализовать «скользящее среднее» для таблицы contests всего с двумя столбцами id и ideas_count (int) в MySQL:

Для каждой строки в contests верните id и среднее значение ideas_count для последних 10 строк до и включая текущую.

Вот где я застрял:

select 
  id, (
    select avg(ideas_count) from (
      select * from contests c2 where c2.id<=c1.id order by id desc limit 10
    ) prev
  ) 
from 
  contests c1
order by 
  id asc;

MySQL возвращает ошибку: "Unknown column 'c1.id' in 'where clause'"

Почему это?

Как я могу заставить это работать?

Обновить

select 
  id, (
    select avg(ideas_count) from contests c2 
    where c2.id <= c1.id order by id desc limit 10
  ) 
from 
  contests c1
order by 
  id asc;

не будет работать, потому что он вычисляет avg first и применяет limit after , тогда как мне нужен < сильное> среднее значение последних 10 строк .

Обновление 2

Добавлен SQLFiddle.

1
Alexander Presber 23 Фев 2016 в 13:54

3 ответа

Лучший ответ

Использование пары порядковых номеров, сгенерированных в подзапросах. Затем присоединение к подзапросам на основе этих порядковых номеров.

SELECT sub1.id, 
        AVG(sub2.ideas_count) AS rolling_average
FROM
(
    SELECT id, ideas_count, @seq1:=@seq1 + 1 AS seq
    FROM contests
    CROSS JOIN (SELECT @seq1:=0) sub0
    ORDER BY id
) sub1
INNER JOIN
(
    SELECT id, ideas_count, @seq2:=@seq2 + 1 AS seq
    FROM contests
    CROSS JOIN (SELECT @seq2:=0) sub0
    ORDER BY id
) sub2
ON sub2.seq BETWEEN sub1.seq -9 AND sub1.seq
GROUP BY sub1.id
3
Kickstart 23 Фев 2016 в 13:28

Надеюсь, это поможет

select id , avg(ideas_count)
from (
    select t1.id, t1.t_id, t1.ideas_count, @i:=if(@j < t1.id, 1, @i+1) as i, @j:=t1.id as j
    from ( select c1.id, c2.id as t_id, c2.ideas_count
           from contests c2 join contests c1 on c2.id<=c1.id 
           order by c1.id asc, c2.id desc
        ) as t1
        join (select @i:=0, @j:=0) as t2
    ) as t3
where i <=10
group by id
1
Hieu Vo 23 Фев 2016 в 13:07

Вы можете обновить свой запрос, чтобы он был:

select 
id, (select avg(ideas_count) from  
(select * from contests c2) prev where prev.id<=c1.id  order by prev.id desc limit 10 )     
as average 
from 
contests c1
order by id asc;
0
Gouda Elalfy 23 Фев 2016 в 11:20