Member 11166599 Ответов: 1

Как оптимизировать мой запрос union all


Привет,

У меня есть таблица mysql, которая хранит данные о присутствии датчика в каждой временной метке в нескольких областях.
Если у меня есть, например, 3 области для определенной временной метки, моя таблица будет выглядеть следующим образом:

timestamp    areas_id    is_in_or_out
 ts1             25          1
 ts1             26          0
 ts1             27          0
 ts2             25          1
 ts2             26          0
 ts2             27          0
 ts3             25          0
 ts3             26          0
 ts3             27          1


Я использую следующий запрос для каждого из них areas_id с union all чтобы вывести в одной таблице временные периоды того, как мой датчик перемещался между областями и сколько он оставался в каждой области.
select t.a_id, min(t.timestamp) starttime,max(t.timestamp) endtime, 
t.is_flag from(SELECT *,
ROW_NUMBER() OVER(ORDER BY a.timestamp) - ROW_NUMBER() OVER(PARTITION BY 
a.is_flag ORDER BY a.timestamp) as GRP
FROM tablename a where areas_id=25 ) t
group by is_flag , GRP, a_id 

Желаемый результат:
starttime     endtime      areas_id      is_in_or_out
 ts1           ts2           25             1
 ts1           ts3           26             0
 ts1           ts2           27             0
 ts3           tsx           27             1

Вот мой dbfiddle: DBFIDDLE
Все работает нормально, кроме времени исполнения на целый день.
Есть ли другой способ сделать это быстрее? Может быть, более быстрый Куэрри?

Спасибо.

Что я уже пробовал:

Вот мой dbfiddle: DBFIDDLE
Мой запрос делает то, что мне нужно, но он занимает много времени в течение целого дня.

1 Ответов

Рейтинг:
1

Maciej Los

Извините, но описание вопроса не совсем понятно, потому что:
1) Если вы хотите получить минимальные и максимальные значения для timestamp поле, вам не нужно писать несколько подзапросов (для каждого areas_id); этот group by заявление уже делает это,
2) Если вы хотите получить непрерывное время для каждого areas_id, тогда вам нужно прочитать это: SQL пробелов и островов в последовательностях - простой разговор[^]

Я бы настоятельно рекомендовал использовать правильный тип данных для даты и времени. Вместо varchar(21), использовать datetime или timestamp. Видеть: С mysql :: mysql с 8.0 справочник :: 11.2.2 дата, DateTime и timestamp типы[^]

Я пробовал ниже запроса:

SELECT areas_id, MIN(timestamp) starttime, MAX(timestamp) endtime, is_in_or_out
FROM inouts
GROUP BY areas_id, is_in_or_out;

Результирующий набор такой же, как у вас, но время выполнения в два раза меньше. Для такой небольшой порции данных разница велика!

Удачи вам!