[MySQL] выбор ближайшего (в любую сторону) значения

12
toxic steel
На сайте с 28.12.2007
Offline
175
8742

размышляю над задачей:

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

если есть 123 и 129, то 129 - ближайшее

если есть 127 и 143, то ближайшее - 127

понятно, что это можно сделать математикой с подзапросами, начерно даже примерно понятно как (ещё не решил чего выбирать при наличии 127 и 129, правда).

но может есть какая-то дефолтная функция?

буду признателен за название. (ну или за краткий, но ёмкий ответ "нету")

* не дефолтное, но изящное и нересурсоёмкое решение тоже приветствуется.

погуглил, но у гугла чё-то с английским не то, он меня не понимает :)

Any ideas

Есть отличные, недорогие рекламные места на агрофоруме (http://farmerforum.ru/viewtopic.php?t=1725)! Клуб истинных ценителей денег (http://coinshunter.ru/).
Слава Шевцов
На сайте с 23.07.2005
Offline
370
#1

Двумя запросами ищем ближайшие цифры по обе стороны

SELECT id FROM table WHERE id > 128 ORDER BY id ASC LIMIT 1

SELECT id FROM table WHERE id < 128 ORDER BY id DESC LIMIT 1

Потом сравниваем разности относительно 128 и находим ближайшее число. Нагрузки на базу минимальные.

Неизменность точки зрения неизменно порождает иллюзию понимания.
toxic steel
На сайте с 28.12.2007
Offline
175
#2

Слава Шевцов, это я и имел ввиду под

toxic steel:
математикой с подзапросами

а йа хачу шоб красывенько было :D

покамест меня успели пнуть в сторону расчёта разницы модулей чисел. сижу изучаю как пользовать "абсолютное значение действительного числа", ибо первый раз в лоб сталкиваюсь с этой пользительной фичей :)

видимо действительно копать надо в эту сторону.

N
На сайте с 06.05.2007
Offline
419
#3

select .. where v != 128 order by abs(128-v) limit 1;

Но зачем? это всегда будет тормозить.

Кнопка вызова админа ()
toxic steel
На сайте с 28.12.2007
Offline
175
#4
netwind:
это всегда будет тормозить

order by abs жестковато конечно, хотя уже значительно красившее. я размышлял о [min(позапрос с abs)]* - стоит ли начать думать про order, или продолжать развивать тему с min()?

* это я грубо.

тормозить особо не на чем: выборка будет производиться при добавлении новой публикации - т.е. уже не часто. и размер таблицы в пределах 50 тысяч с заложеным на всякий пожарный буфером *50 :) рабочее состояние - 500-1000 строк.

netwind:
Но зачем?

для скиллапа в первую очередь.

N
На сайте с 06.05.2007
Offline
419
#5

toxic steel, да вы затейник.

select * from t where v = 128+ ( select min(abs(v-128)) from t where v != 128) limit 1;

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

по-прежнему лучший запрос уже озвучили во втором сообщении.

toxic steel
На сайте с 28.12.2007
Offline
175
#6
netwind:
да вы затейник.

ещё какой :) такого могу напридумывать :)

netwind:
select * ...

спасибо, но уж мне прям так подробно-то не надо. мне "номера главы в мануале" достаточно, строчку я сам найду. в этом весь смысл, собственно ;)

netwind:
школьный курс математики

нда, приходится вспоминать :)

netwind:
как упражнение на подзапросы

скорей как кружевная салфеточка на телевизоре :D (меня не парит, а бабушка считает, что это красиво). итого, самое главное, чтоб красивости в итоге не парили (в данном случае базу/процессор) :)

просто есть сейчас время/возможность вкурить этот вопрос и по*эстетствовать.

* возможно - "псевдо"

netwind:
чисто как упражнение

это будет в итоге иметь реальное применение. т.е. теоретизирование не в пустую.

toxic steel добавил 12.01.2009 в 03:18

netwind:
по-прежнему лучший запрос уже озвучили во втором сообщении.

у меня тесты обратное показали.

на 1 000 запросов в первом варианте потребовалось 2,7 секунды, при том, что

для второго и третьего по 1,4 и 1,2

на 10 000 - 25 12 и 14

N
На сайте с 06.05.2007
Offline
419
#7

думаю у вас просто данных мало было.

в этом случае два простых запроса получаются медленнее одного из-за накладных расходов.

[Удален]
#8

не заметил 4й пост =)

лучший вариант, только зачем сравнивать на неравенство. Order by abs сработает быстрее чем два запроса, и сравнимо с подзапросом. От наличия индекса зависит и памяти в пуле =)

toxic steel
На сайте с 28.12.2007
Offline
175
#9
neolord:
не заметил 4й пост =)
лучший вариант

быстрее чем первый вариант. но explain говорит, что лучше всё-таки третий, ибо не пользует filesort и по времени они работают одинаково со второмы - замеры в конце поста #7.

Слава Шевцов
На сайте с 23.07.2005
Offline
370
#10
toxic steel:
по времени они работают одинаково со второмы - замеры в конце поста #7.

Это замеры на скорость парсинга запросов ;)

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий