Сведения о вопросе

DUNKER

12:58, 24th August, 2020

Теги

Используйте предложение LIKE в части внутреннего соединения

Просмотров: 399   Ответов: 10

Могу ли я / должен ли я использовать критерий LIKE как часть внутреннего соединения при построении сохраненного procedure/query? я не уверен, что задаю правильный вопрос, поэтому позвольте мне объяснить.

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

SELECT Id, Name, Description
  FROM dbo.Card
 WHERE Description LIKE '%warrior%' 
       OR
       Description LIKE '%fiend%' 
       OR 
       Description LIKE '%damage%'

Но трюк, который я немного подхватил, чтобы сделать разбор списка "strongly typed" в хранимой процедуре, заключается в том, чтобы разобрать список в табличную переменную/временную таблицу, преобразовать его в нужный тип и затем выполнить внутреннее соединение с этой таблицей в моем конечном результирующем наборе. Это отлично работает при отправке, скажем, списка целых чисел IDs в процедуру. Я заканчиваю тем, что у меня есть последний запрос, который выглядит следующим образом:

SELECT Id, Name, Description
  FROM dbo.Card
       INNER JOIN @tblExclusiveCard ON dbo.Card.Id = @tblExclusiveCard.CardId

Я хочу использовать этот трюк со списком строк. Но поскольку я ищу конкретное ключевое слово, я собираюсь использовать предложение LIKE. Поэтому в идеале я думаю, что мой последний запрос будет выглядеть следующим образом:

SELECT Id, Name, Description
  FROM dbo.Card
       INNER JOIN @tblKeyword ON dbo.Card.Description LIKE '%' + @tblKeyword.Value + '%'

Это possible/recommended?

Есть ли лучший способ сделать что-то подобное?


Причина, по которой я ставлю подстановочные знаки на обоих концах предложения, заключается в том, что в текстах карт используются термины "archfiend", "beast-warrior", "direct-damage" и "battle-damage".

У меня складывается впечатление, что в зависимости от производительности я могу либо использовать указанный запрос, либо использовать полнотекстовый поиск по ключевым словам для выполнения той же задачи?

Кроме того, что сервер делает текстовый индекс для полей, которые я хочу найти в тексте, есть ли что-то еще, что мне нужно сделать?



  Сведения об ответе

VERSUION

01:51, 6th August, 2020

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

Попробуйте выполнить полнотекстовый поиск, если вы используете сервер SQL, или проверьте одну из реализаций Lucene . Джоэл рассказывал о своем недавнем успехе с ним.


  Сведения об ответе

lesha

16:20, 10th August, 2020

Попробовать это

    select * from Table_1 a
    left join Table_2 b on b.type LIKE '%' + a.type + '%'

Эта практика не идеальна. Используйте с осторожностью.


  Сведения об ответе

ASER

18:02, 17th August, 2020

Похоже, что вы ищете полнотекстовый поиск. Потому что вы хотите запросить набор ключевых слов по описанию карты и найти какие-либо хиты? Правильно?


  Сведения об ответе

PAGE

05:13, 11th August, 2020

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

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


  Сведения об ответе

SEEYOU

10:59, 6th August, 2020

@Dillie-O
Насколько велик этот стол?
Что такое тип данных поля описания?

Если любой из них мал, то полнотекстовый поиск будет излишним.

@Dillie-O
Может быть, не тот ответ, который вы ищете, но я бы выступил за изменение схемы...

предлагаемая схема:

create table name(
    nameID identity / int
   ,name varchar(50))

create table description(
    descID identity / int
   ,desc varchar(50)) --something reasonable and to make the most of it alwase lower case your values

create table nameDescJunc(
    nameID  int
    ,descID int)

Это позволит вам использовать индекс без необходимости реализации болта на решение, и сохраняет ваши данные атомарными.

связанный: рекомендуемый дизайн базы данных SQL для тегов или меток


  Сведения об ответе

lool

23:29, 29th August, 2020

трюк, который я подхватил совсем недавно. чтобы сделать разбор списка "strongly typed" в хранимая процедура предназначена для анализа список в табличную переменную / временную стол

Я думаю, что вы, возможно, намекаете здесь на то, чтобы поместить ключевые слова для включения в таблицу, а затем использовать реляционное разделение для поиска совпадений (можно также использовать другую таблицу для слов для исключения). Пример работы в SQL см. В разделе Поиск по ключевым словам от Joe Celko .


  Сведения об ответе

SEEYOU

20:11, 18th August, 2020

попробовать его...

select * from table11 a inner join  table2 b on b.id like (select '%'+a.id+'%') where a.city='abc'.

Это работает на меня.:-)


  Сведения об ответе

JUST___

20:36, 18th August, 2020

Производительность будет зависеть от фактического сервера, который вы используете, а также от схемы данных и объема данных. С текущими версиями MS SQL Server этот запрос должен работать просто отлично (MS SQL Server 7.0 имел проблемы с этим синтаксисом, но он был решен в SP2 ).

Вы прогнали этот код через профилировщик? Если производительность достаточно быстра и данные имеют соответствующие индексы на месте, вы должны быть полностью настроены.


  Сведения об ответе

Chhiki

09:39, 12th August, 2020

Как '%fiend%' никогда не будет использовать поиск, LIKE 'fiend%' будет. Просто поиск по маске не sargable


  Сведения об ответе

PIRLO

17:11, 25th August, 2020

Попробовать это;

SELECT Id, Name, Description
FROM dbo.Card
INNER JOIN @tblKeyword ON dbo.Card.Description LIKE '%' + 
                                CONCAT(CONCAT('%',@tblKeyword.Value),'%') + '%'


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться