mysql, ограничивающий количество строк в сравнении на основе условия - PullRequest
0 голосов
/ 15 октября 2018

У меня есть таблица "my_table" с 2 столбцами

 1. Timestamp (ts)
 2. Value (val)

Мне нужно возвращать для каждой временной метки среднее значение из 10 последних значений, которые встречаются на или перед временной меткой.

Я могу сделать что-то похожее со следующим запросом:

SELECT t2.ts as time, 
       AVG(t1.val) as avg_val 
FROM table_name as t1, table_name as t2 
WHERE t1.ts <= t2.ts 

Возвращает метку времени и среднее значение всех значений, которые встречаются в или до этой метки времени.Мне нужно изменить этот запрос, чтобы получить среднее из 10 последних значений, а не всех значений.

PS: Извиняюсь за неправильный заголовок вопроса.Не был уверен, как это сделать.

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Не существует простого способа выразить этот запрос в MySQL до версии 8 - даже с использованием переменных.Я не собираюсь ручаться за производительность, но это должно делать то, что вы хотите:

SELECT t1.ts, t1.val, AVG(t2.val)
FROM t t1 LEFT JOIN
     t t2
     ON t2.ts <= t.ts AND
        t2.ts >= (SELECT t3.ts
                  FROM t t3
                  WHERE t3.ts <= t1.ts
                  ORDER BY t3.ts DESC
                  LIMIT 9, 1
                 )
GROUP BY t1.ts, t1.val;

Конечно, в 8+ это просто:

select t.*,
       avg(t.val) over (order by ts rows between 9 preceding and current row) as avg_10
from t;
0 голосов
/ 15 октября 2018

Игнорировать предыдущий ответ.Вы можете использовать «ранг бедняка» для ранжирования строк, отсортированных по метке времени.Вы можете объединить результат самостоятельно, чтобы найти предыдущие 9 строк для каждого ранга:

SELECT a.ts, AVG(c.val)
FROM (
    SELECT t1.ts, COUNT(t2.ts) AS rank
    FROM t AS t1
    INNER JOIN t AS t2 ON t2.ts <= t1.ts
    GROUP BY t1.ts
) AS a
INNER JOIN (
    SELECT t1.ts, COUNT(t2.ts) AS rank
    FROM t AS t1
    INNER JOIN t AS t2 ON t2.ts <= t1.ts
    GROUP BY t1.ts
) AS b ON b.rank BETWEEN a.rank - 9 AND a.rank
INNER JOIN t AS c ON b.ts = c.ts
GROUP BY a.ts

Я понимаю, что это немного неуклюже, но это может быть лучше, чем коррелированные подзапросы при определенных условиях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...