Моя исследовательская группа каждую минуту собирает информацию о микромобильном велосипеде / самокате (при этом фактическая информация обновляется каждые 3-5 минут), которая предоставляет информацию о местонахождении велосипеда / скутера. Каждая недублирующаяся запись сохраняется в таблице freeBikeStatus:
CREATE TABLE `freeBikeStatus` (
`bike_id` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`lon` double DEFAULT NULL,
`lat` double DEFAULT NULL,
`is_reserved` bigint(20) DEFAULT NULL,
`is_disabled` bigint(20) DEFAULT NULL,
`soc` double DEFAULT NULL,
`provider` varchar(255) DEFAULT NULL,
`system_name` varchar(255) NOT NULL,
`timestamp` bigint(20) NOT NULL,
`vehicle_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`bike_id`,`system_name`,`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Однако существует масса избыточной информации, потому что сам велосипед может не двигаться, но все равно будет записан в нескольких строках с разными отметки времени. Это может увеличить размер нашей базы данных в 40-50 раз, поэтому необходим запрос для уменьшения размера и устранения избыточной информации. В качестве примера:
==============================================
| row | bikeid | lat | lon | timestamp | ... |
==============================================
| 1 | a | X | Y | 1:01 | ... |
| 2 | a | X | Y | 1:03 | ... |
| 3 | a | X | Y | 1:05 | ... |
| 4 | a | X | Y | 1:08 | ... |
| 5 | a | Z | Y | 1:12 | ... |
| 6 | a | Z | Y | 1:15 | ... |
| 7 | a | Z | Y | 1:17 | ... |
| 8 | a | Z | Y | 1:19 | ... |
| 9 | a | X | Y | 1:22 | ... |
| 10 | a | X | Y | 1:25 | ... |
| 11 | a | X | Y | 1:27 | ... |
| 12 | a | X | Y | 1:29 | ... |
Поскольку велосипед фактически не перемещался с 1:01 на 1:08, с 1:12 на 1:19 и с 1:22 на 1:29, между рядами нет необходимости. Поэтому мы хотели бы заменить приведенную выше таблицу на таблицу ниже:
==============================================
| row | bikeid | lat | lon | timestamp | ... |
==============================================
| 1 | a | X | Y | 1:01 | ... |
| 4 | a | X | Y | 1:08 | ... |
| 5 | a | Z | Y | 1:12 | ... |
| 8 | a | Z | Y | 1:19 | ... |
| 9 | a | X | Y | 1:22 | ... |
| 12 | a | X | Y | 1:29 | ... |
Я придумал следующий запрос, основанный на аналогичном вопросе StackOverFlow ( Выбор первого и последнего значений в группе ).
WITH
t1 AS (
SELECT * AS lon, lat
FROM freeBikeStatus
),
t2 AS (
SELECT t1.*,
FIRST_VALUE(timestamp) OVER (PARTITION BY lat, lon ORDER BY timestamp) AS begin,
LAST_VALUE(timestamp) OVER (PARTITION BY lat, lon ORDER BY timestamp) AS end
FROM t1
)
SELECT * FROM t2
GROUP BY lat, lon
ORDER BY lat, lon
Однако кажется, что в этом примере есть небольшая разница (что привело к запросу выше). Если велосипед возвращается к той же широте / долготе, я считаю, что запрос удалит все временные точки, даже если он переместится из точки A -> B -> A, что приведет к вырезанию одной конечной точки и одной начальной точки. Есть ли способ изменить этот запрос, чтобы учесть это?