2013-03-23 1 views
3

У вас есть столбец foo, определенного типа строки, с индексом в этом столбце. Вы хотите, чтобы SELECT из таблицы WHERE столбец foo имеет префикс 'pre'. Очевидно, что индекс должен помочь здесь.SELECT префикс строки с использованием индекса

Вот самый очевидный способ поиска префикса:

SELECT * FROM tab WHERE foo LIKE 'pre%'; 

К сожалению, это не получает оптимизировано для использования индекса (в Oracle или Postgres, по крайней мере).

Ниже, однако, делает работ:

SELECT * FROM tab WHERE 'pre' <= foo AND foo < 'prf'; 

Но есть ли более эффективные способы достигнуть этого, или есть способы сделать выше более изящным? В частности:

  • Мне нужна функция от 'pre' к 'prf', но это должно работать для любой основной сортировки. Кроме того, это сложнее, чем выше, потому что, если искать, например, 'prz', тогда верхняя граница должна быть 'psa' и так далее.
  • Могу ли я отрисовать это в хранимой функции/процедуре и все еще попадать в индекс? Значит, я мог написать что-то вроде ... WHERE prefix('pre', foo);?

Ответы для всех СУБД оценены.

+0

Что? К сожалению, это «оптимизируется для использования индекса»? Было так плохо? Конечно, «начинается с» поиска использует индекс, если это возможно. Слава богу, это так. Я вас неправильно понял? – alzaimar

+0

lol, извините, я случайно слово «не»! отредактировано – jameshfisher

+0

О, и вы имеете в виду, что есть конструкция «начинается с» в SQL? Я ничего не могу с этим поделать. – jameshfisher

ответ

0

База данных здесь очень важна. Так получилось, что SQL Server делает эту оптимизацию для like.

Один из способов сделать что-то вроде этого:

where foo >= 'pre' and foo <= 'pre+'~' 

«~» имеет большой 7-битное значение ASCII из печатаемого символа, так что в основном больше, чем все остальное. Однако это может быть проблемой, если вы используете широкие символы или нестандартный набор символов.

Вы не можете абстрагировать это на функцию, потому что использование функции обычно исключает использование индексов. Если вы всегда смотрите на первые три символа, то в Oracle вы можете создать индекс для этих трех символов (что-то называемое «функциональным индексом»).

+0

Я не думаю, что 'foo <= 'pre ~'' работает, потому что он вырезает значения, как '' pre ~ fix''. Если вы используете сравнение '<=', значение должно быть «pre ~~~~~~~~~~ ...», продолжающимся вечно. Использование функций: Я думаю, что вы правы. Возможно, макросы в SQL будут приятными, но это пирог в небе. – jameshfisher

-3

Как насчет

select * from tab where foo between 'pre' and 'prf' and foo != 'prf' 

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

+0

Вы используете инклюзивный конечный диапазон, затем должны указать другое условие, чтобы сделать исключение эксклюзивным? Почему бы не 'foo> = 'pre' AND foo <'prf''? – ErikE

+0

Хороший вопрос. Я не пробовал, но из моих кишок кажется, что «между» лучше. Хм ... Я слишком верим в то, что я должен больше быть в доказательстве? – alzaimar

+0

Является ли 'x МЕЖДУ l И h' не просто сахаром для' l <= x И x <= h'? – jameshfisher