2015-02-13 5 views
2

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

В любом случае проблема заключается в том, что у меня есть таблица данных, каждая из которых добавляет новую строку (представьте структуру {id, timestamp (datetime), value}). Я хотел бы сделать один запрос для MySQL, чтобы пройти через таблицу и вывести только первое значение каждой минуты.

Я думал об этом с несколькими запросами с LIMIT и datetime> = (начало минуты), но с объемом данных, которые я собираю, это много запросов, поэтому было бы лучше производить данные в один запрос.

Образец данных:

id datetime    value 
1 2015-01-01 00:00:00 128 
2 2015-01-01 00:00:01 127 
3 2015-01-01 00:00:04 129 
4 2015-01-01 00:00:05 127 
... 
67 2015-01-01 00:00:59 112 
68 2015-01-01 00:01:12 108 
69 2015-01-01 00:01:13 109 

Где я хочу результат, чтобы выбрать строки:

1 2015-01-01 00:00:00 128 
68 2015-01-01 00:01:12 108 

Любые идеи?

Спасибо!

EDIT: Забыл добавить, данные, в то время как каждый второй, не может быть надежно на первую секунду каждой минуты - это может быть: 30 или: 01, а не: 00 секунд мимо минуты

EDIT 2 : Хороший (обязательно не требуется для ответа) запрос будет гибким, чтобы также принимать произвольное количество минут (а не одну строку каждую минуту)

+1

Добавьте свои репрезентативные данные образца и ожидаемый результат. Также опубликуйте свой лучший снимок при решении проблемы. –

+0

Вы говорите, что у вас может быть менее 60 строк за заданную минуту. Если какая-то минута вообще не имеет каких-либо значений, что бы вы хотели увидеть в результирующем наборе на эту минуту? –

ответ

1
SELECT t2.* FROM 
(SELECT MIN(`datetime`) AS dt 
    FROM tbl 
GROUP BY DATE_FORMAT(`datetime`,'%Y-%m-%d %H:%i') 
) t1 
JOIN tbl t2 ON t1.dt = t2.`datetime` 

SQLFiddle

Или

SELECT * 
FROM tbl 
WHERE dt IN (SELECT MIN(dt) AS dt 
       FROM tbl 
       GROUP BY DATE_FORMAT(dt,'%Y-%m-%d %H:%i')) 

SQLFiddle

SELECT t1.* 
FROM tbl t1 
LEFT JOIN (
    SELECT MIN(dt) AS dt 
    FROM tbl 
    GROUP BY DATE_FORMAT(dt,'%Y-%m-%d %H:%i') 
) t2 ON t1.dt = t2.dt 
WHERE t2.dt IS NOT NULL 

SQLFiddle

+0

'DATE_FORMAT' кажется довольно дорогостоящей операцией для этой цели. –

+0

На моем (по общему признанию, не очень мощном) сервере разработки MySQL эти запросы занимают в области 30 секунд, чтобы заполнить 2 000 000 строк, что довольно долгое время – CallumA

+0

@CallumA: как отметил @Jordan, 'DATE_FORMAT' стоит дорого, но я не знаю другого решения. Вы можете попытаться использовать 'LEFT JOIN', поскольку он считает самым быстрым решением для объединения в MySQL для непустых столбцов. – potashin

-1

select * from table where timestamp LIKE "%-%-% %:%:00" может работать.

Это похоже на этот вопрос: Stack Overflow Date SQL Query Question

Edit: Это, вероятно, будет работать лучше:

`выберите , date_format (метку времени,«% Y-% m-% d% H: % я '), как the_minute, граф () из таблицы группы по the_minute порядка the_minute

Похожих на этот вопрос здесь: mysql select date format

-1

я не совсем уверен, но вы можете попробовать это:

SELECT MIN(timestamp) FROM table WHERE YEAR(timestamp)=2015 GROUP BY DATE(timestamp), HOUR(timestamp), MINUTE(timestamp) 
0

В MS SQL Server Я хотел бы использовать CROSS APPLY, но, насколько я знаю, MySQL не имеет, поэтому мы можем подражать ему.

Убедитесь, что у вас есть указатель на колонке datetime.

Создайте table of numbers или в вашем случае таблицу минут. Если у вас есть таблица чисел, начиная с 1, тривиально превратить ее в минуты в нужном диапазоне.

SELECT 
    tbl.ID 
    ,tbl.`dt` 
    ,tbl.value 
FROM 
    (
    SELECT 
     MinuteValue 
     , (
     SELECT tbl.id 
     FROM tbl 
     WHERE tbl.`dt` >= Minutes.MinuteValue 
     ORDER BY tbl.`dt` 
     LIMIT 1 
     ) AS ID 
    FROM Minutes 
) AS IDs 
    INNER JOIN tbl ON tbl.ID = IDs.ID 

Для каждой минуты найдите один ряд, который имеет отметку времени больше минуты. Я не знаю, как вернуть полную строку, а не один столбец в MySQL в вложенном SELECT, поэтому сначала я создаю временную таблицу с двумя столбцами: Minute и id из исходной таблицы, а затем явно просматриваю строки из оригинального стола, зная их IDs.

SQL Fiddle

Я создал таблицу протокола в SQL Fiddle с нужными значениями, чтобы сделать пример простой. В реальной жизни у вас будет более общий стол.

Адрес SQL Fiddle, который использует таблицу чисел, только для иллюстрации.

В любом случае, вы должны знать заранее, как-то диапазон дат/чисел вы заинтересованы.

Тривиально заставить его работать на любом интервале минут. Если вам нужны результаты каждые 5 минут, просто создайте таблицу минут, которая имеет значения не каждые 1 минуту, а каждые 5 минут. Основной запрос останется прежним.

Это может быть более эффективно, потому что здесь вы не присоединяетесь к большой таблице и не выполняете вычисления в столбце datetime, поэтому сервер должен иметь возможность использовать индекс на нем.

Пример, который я сделал, предполагает, что за каждую минуту в большой таблице есть по крайней мере одна строка. Если возможно, что есть несколько минут, у которых нет каких-либо данных, вам нужно добавить дополнительную проверку в предложении WHERE, чтобы убедиться, что найденная строка все еще находится в пределах этой минуты.

+0

Что вы в конечном итоге решили сделать? Как вы решили проблему? Был ли какой-нибудь из ответов достаточно полезным, чтобы вы могли принять ответ? –

Смежные вопросы