имея число найти диапазон в который оно входит

Dr_Jones

Новичок
имея число найти диапазон в который оно входит

Нужно одним запросом узнать в какой диапазон входит число
Например
имеем
k=12

и записи в базе

k | v
1 | 10
2 | 14
3 | 56
4 | 98
9 | 33
10| 7
20| 88
22| 89
30| 90

нужно найти диапазон для k=12, т.е. 10-20. Желательно одним запросом
 

WP

^_^
[sql]
(SELECT MAX( `k` ) AS `n` FROM `table` WHERE `k` <= 12)
UNION
(SELECT MIN( `k` ) AS `n` FROM `table` WHERE `k` >= 12)
[/sql]
 

Фанат

oncle terrible
Команда форума
меня всегда умиляет, когда в ответ на желание одним запросом пишут юнион.
просто офигенная сообразительность
 

Dr_Jones

Новичок
Автор оригинала: Фанат
меня всегда умиляет, когда в ответ на желание одним запросом пишут юнион.
просто офигенная сообразительность
Как я только не пробовал
 

zerkms

TDD infected
Команда форума
подобный вопрос был "недавно" думаю месяца 3 назад, не более
так что в поиск ;)

WP
решение было в 1 запрос как ни странно ;)
 

Dr_Jones

Новичок
Автор оригинала: zerkms
подобный вопрос был "недавно" думаю месяца 3 назад, не более
так что в поиск ;)

WP
решение было в 1 запрос как ни странно ;)
искал, такого небыло. Был похожый по нахождению ближайшего числа (одного), а мне нужно длижайшее с верхи и снизу (два числа)

-~{}~ 03.06.06 18:22:

Автор оригинала: Фанат
Одно только непонятно - зачем
Зачем пробовал, или зачем находить диапазон?

Т.к. для k=12 нет значений v, их нужно вычислить из диапазона ближайших значений
 

SelenIT

IT-лунатик :)
chira
Верно ли я понимаю, что это скорее "спортивный" пример, и индексы при таком варианте грустят в стороне?
 

chira

Новичок
SelenIT

на моих данных:
Код:
mysql> select * from t;
+----+---------+
| id | data_id |
+----+---------+
|  1 |       1 |
|  2 |       1 |
|  1 |       1 |
|  2 |       1 |
|  1 |       2 |
|  4 |       2 |
|  1 |       3 |
|  1 |       3 |
|  3 |       1 |
|  1 |       5 |
|  2 |       5 |
|  3 |       5 |
|  4 |       5 |
|  5 |      10 |
|  6 |      20 |
|  7 |      22 |
|  8 |      30 |
+----+---------+
17 rows in set (0.00 sec)

mysql> explain
    -> select MAX(IF(data_id<=21,data_id,NULL)) start, MIN(IF(data_id>=21,data_id,NULL)) end
    -> from t
    -> ;
+----+-------------+-------+-------+---------------+-----------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key       | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-----------+---------+------+------+-------------+
|  1 | SIMPLE      | t     | index | NULL          | t_data_id |       5 | NULL |   17 | Using index |
+----+-------------+-------+-------+---------------+-----------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> select MAX(IF(data_id<=21,data_id,NULL)) start, MIN(IF(data_id>=21,data_id,NULL)) end
    -> from t
    -> ;
+-------+------+
| start | end  |
+-------+------+
|    20 |   22 |
+-------+------+
1 row in set (0.00 sec)

mysql> select version();
+-----------+
| version() |
+-----------+
| 4.1.11-nt |
+-----------+
1 row in set (0.02 sec)
 

SelenIT

IT-лунатик :)
chira, спасибо за поучительный пример!

P.S. Даже не знал, что бывает такое...
Код:
...+---------------+-----------+...
...| possible_keys | key       | ...
...+---------------+-----------+...
...| NULL          | t_data_id | ...
...+---------------+-----------+...
Оказывается, бывает. Наверное, сказывается то, что ищутся заведомо не более 2-х записей?
 

chira

Новичок
Dr_Jones
Но кроме значения k нужно значение v
Код:
select MAX(IF(k<=12,k,NULL)) startk
, MIN(IF(k>=12,k,NULL)) endk
, SUBSTR( MAX( CONCAT( LPAD(IF(k<=12,k,NULL),10,'0'), v )),11) startv
, SUBSTR( MIN( CONCAT( LPAD(IF(k>=12,k,NULL),10,'0'), v )),11) endv
from mytable
это скорее похоже на workaround, но это вариант из MySQL мануала ...
с индексами здесь сложнее, возможно к его использованию при определении плана в MySQL, может подтолкнуть не влияющее на результат выражение:
where k IS NOT NULL
или создание составного индекса k,v
 

DiMA

php.spb.ru
Команда форума
Есть похожая задача: табличка хранит диапазоны ип-сетей и имя города. Можно легко одним запросом найти в какой диапазон входит текущий ип. Фишка в том, чтобы передней верхней частью человека решать задачу - а именно, хранить данные в базе так, чтобы их удобно и оптимально было достать. И все мгновенно работает на больших базах.
 

chira

Новичок
Согласен с SelenIT по поводу "спортивного интереса", такие задачки могут помочь понять, как нужно делать и как не стоит, в реальном проекте.
 
Сверху