Самый эффективный способ найти ближайшее целое число в MySQL? - PullRequest
6 голосов
/ 20 августа 2009

У меня есть таблица в базе данных MySQL, из которой я хочу выбрать строку с ближайшей временной меткой к другой данной временной метке.

time - столбец отметки времени (целочисленная отметка времени UNIX). Я выбрал 1250710000 произвольно.

Это запрос, который я предложил, и мне интересно, есть ли более эффективный способ сделать это:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table
 ORDER BY time_dist ASC LIMIT 1

Это лучший способ сделать это?

Ответы [ 3 ]

10 голосов
/ 20 августа 2009

Предполагая, что time проиндексирован, вы можете получить запись next почти бесплатно:

SELECT * FROM table WHERE time > 1250710000 ORDER BY time LIMIT 1

И если я не ошибаюсь, то же самое должно относиться к предыдущей записи, MySQL будет просто читать индекс в обратном порядке. Используйте СОЮЗ из двух, упорядочите их по дате и времени! Результат будет выглядеть так

SELECT *
FROM
(
    (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time > 1250710000 ORDER BY time ASC LIMIT 1)
    UNION ALL
    (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time < 1250710000 ORDER BY time DESC LIMIT 1)
) AS tmp
ORDER BY time_diff
LIMIT 1

В идеале вместо > и < следует использовать >= и <= и исключать опорную запись, используя ее первичный идентификатор, для учета записей, использующих одну и ту же метку времени.

1 голос
/ 20 августа 2009

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

ВЫБРАТЬ МАКС. (Время) КАК пред. ГДЕ время <1250710000; </p>

ВЫБРАТЬ МИН. (Время) КАК следующее ГДЕ время> 1250710000;

SELECT MIN (ABS (предыдущая), ABS (следующая));

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

1 голос
/ 20 августа 2009

Как сказал Эван, у тебя все хорошо. Я бы порекомендовал индекс для этого поля отметки времени, чтобы MySQL мог сканировать меньший индекс, а не всю таблицу. Кроме того, я бы попробовал «бокс», чтобы увидеть, может ли индекс ускорить процесс:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
WHERE time between(1250610000,1250810000)
ORDER BY time_dist ASC LIMIT 1

Вышеуказанные ограничения для запроса примерно +/- 1 день. Вам нужно будет сделать несколько тестов, чтобы проверить, выполняется ли дополнительное сканирование индекса (предложение where) быстрее, чем вычисление ABS () для всех записей в таблице.

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