Эффективно ВЫБЕРИТЕ строку БД, помеченную как последняя версия, и при совпадении с заданным интервалом

У меня есть такая таблица:

id    min    max    version    data
 1     1      10       1         a
 2    11      20       1         b
 3    21      30       1         c

 4     1      10       2         a
 5    11      20       2         b
 6    21      30       2         c

min, max представляют значения key. Каждая (min, max) строка в данной версии гарантированно имеет взаимоисключающие ключевые интервалы.

Предположим, у меня есть значение ключа 5, и мне нужна последняя версия данных для этого ключа. Это означает, что я хочу выбрать строку с id = 4.

Обычно я хочу выбрать набор с самой последней версией, но иногда я могу явно указать номер версии.

То, что у меня есть сейчас, это:

select * from range_table where 5 between `min` and `max` and ver = 2;

Вопрос: есть ли способ автоматически выбрать максимальную версию (max ver), не указывая ее явно? (Под «эффективно» я подразумеваю без изучения всех строк таблицы.)

Чтобы воссоздать таблицу

drop table range_table;
CREATE TABLE `range_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `min` int(11) NOT NULL,
  `max` int(11) NOT NULL,
  `ver` int(11) NOT NULL default 1, 
  `data` CHAR NOT NULL,

  PRIMARY KEY (`id`),
  unique key ver_min_max(ver, `min`, `max`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

insert into range_table (`min`,`max`, ver, data) values
(1, 10, 1, 'a'),
(11, 20, 1, 'b'),
(21, 30, 1, 'c'),
(1, 10, 2, 'a'),
(11, 20, 2, 'b'),
(21, 30, 2, 'd');

person Dennis    schedule 29.12.2014    source источник
comment
Что неэффективного в том, что у вас есть?   -  person AdamMc331    schedule 29.12.2014
comment
Я не уверен, правильно ли я понял, но наличие значения ключа 5 в соответствии с запросом означает, что будет выбрана строка с id=4, а не id=6?   -  person    schedule 29.12.2014
comment
Я не знаю, более ли это эффективно, но один из способов переписать это может быть WHERE 5 BETWEEN min AND max.   -  person AdamMc331    schedule 29.12.2014
comment
@Mc: план выполнения запроса проверяет все строки. Я думаю, что есть способ обнулить одну строку с помощью индекса.   -  person Dennis    schedule 29.12.2014
comment
обновление: больше нет, ... не знаю, почему раньше он проверял все строки, теперь он говорит, что 1 строка проверяется с использованием моего ver_min_max index Остается только один вопрос, см. обновленный раздел вопросов в моем вопросе.   -  person Dennis    schedule 29.12.2014


Ответы (3)


Вы можете занять первый ряд, заказанный по описанию версии...

select * from range_table where 5 between `min` and `max` order by ver desc limit 1;
person dotjoe    schedule 29.12.2014

Если вы заботитесь о производительности, то, в зависимости от размера и/или селективности столбцов, вы можете добавить индекс к столбцу min или max. Если количество версий остается низким для каждого min-max, ваш запрос будет оптимизирован.

person Nicola Ferraro    schedule 29.12.2014

Пожалуйста, попробуйте следующее, чтобы всегда выбирать последнюю версию

select * from range_table where @key between `min` and `max` and ver = (select max (a.ver) as max_ver from range_table as a where @key between a.`min` and a.`max`) 

где @key будет заданным значением ключа.

person Community    schedule 29.12.2014