Как сделать поисковый запрос sql более мощным?

Я написал этот SQL-запрос для поиска в таблице:

SELECT * FROM TableName WHERE Name LIKE '%spa%'

Таблица содержит эти строки, например:

  1. Космическая Компания.
  2. Спа курорт.
  3. Спа отель.
  4. Запасные части.
  5. WithoutTheKeyword.

Я хочу знать, как редактировать этот запрос, чтобы он возвращал результаты, отсортированные следующим образом:

2 Спа-курорт

3 Спа-отель

1 космическая компания

4 Запасные части

Означает элементы, которые содержат точное слово, а затем аналогичные.

6 ответов

Решение

Что -то вроде

Select * from TableName where Name Like 'Spa%'
ORDER BY case when soundex(name) = soundex('Spa') then '1' else soundex(name) end

должно работать нормально.

на самом деле это будет работать лучше

Select * from TableName where Name Like 'Spa%'
ORDER BY DIFFERENCE(name, 'Spa') desc;

Я провел несколько быстрых тестов, и если "Name" находится в NONCLUSTERED INDEX, SQL будет использовать индекс и не будет сканировать таблицу. Кроме того, похоже, что LIKE использует меньше ресурсов, чем charindex (который возвращает менее желательные результаты). Проверено на SQL 2000.

Вы понимаете, я полагаю, что ваша схема почти исключает какую-либо полезность индексов для таких запросов?

Большая проблема - ваше "НРАВИТСЯ"%spa%'". Любой ключ "LIKE", начинающийся с символа подстановки, является автоматическим сканированием таблицы.


РЕДАКТИРОВАТЬ: Я прочитал ваш вопрос, чтобы сказать, что есть одно поле, Имя, со значениями полей что-то вроде "1 космическая компания", "2 Спа-курорт" и т. Д. С номером, за которым следуют слова. И вам нужно было подстановочный знак перед вашим ключом поиска, чтобы пройти номер части. (Это разъясняет мой первый комментарий.) Правильно ли я угадываю или нет?

Следующее должно сделать необходимое, но это неэффективно, делать два полных выбора таблицы, и это также зависит от вашего точного соответствия, разделенного пробелами. Я думаю, что индексация FullText поможет, но это имеет свои собственные издержки.

select distinct * from
(
Select * from TableName 
   where CHARINDEX('spa ', Name) > 0
   or CHARINDEX(' spa', Name) > 0
Union
Select * from TableName 
  where Name Like '%spa%'
)

Если исходить из верхнего примера, то, по крайней мере, в MSSQL2005 изменение CLUSTERED на NONCLUSTERED заставит его выполнить сканирование таблицы. CLUSTERED дает вам индекс поиска. Похоже, это соответствует условиям вопроса.

CREATE TABLE tblTest (ID INT, colname VARCHAR (20))
СОЗДАТЬ КЛАСТЕРНЫЙ ИНДЕКС tstidx1_tblTest ON tblTest(colname);
INSERT tblTest SELECT 1, "Космическая компания"
INSERT tblTest SELECT 2,'Spa Resort'
INSERT tblTest SELECT 3, "Спа Отель"
INSERT tblTest SELECT 4, "Запасные части"
INSERT tblTest ВЫБЕРИТЕ 5, "Без ключа"

ВЫБЕРИТЕ * ОТ tblTest ГДЕ colname LIKE 'Spa%'
ЗАКАЗ ПО РАЗНЫМ (colname, 'Spa') DESC;

DROP TABLE tblTest

Вам в основном нужно определить (точно), какова ваша функция ранжирования на самом деле. Что делать, если у вас есть строка "Спа". или "spa.com"? Как только вы это определили, вам нужно поместить эту логику в ваше предложение ORDER BY. Например:

SELECT
    name
FROM
    Some_Table
WHERE
    name LIKE '%spa%'
ORDER BY
    CASE
        WHEN name LIKE '% ' + @search_word + ' %' THEN 1   -- Notice the spaces
        ELSE 2
    END,
    name

Кроме того, вы можете написать функцию ранжирования и использовать это:

SELECT
    name
FROM
    Some_Table
WHERE
    name LIKE '%' + @search_word + '%'
ORDER BY
    dbo.GetNameMatchRank(name, @search_word)

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

Это должно работать:

Select * from TableName where Name Like '%spa%'
ORDER BY Name
Другие вопросы по тегам