SQL, ГДЕ используется LIKE и сравнивается с полем

#mysql #sql

#mysql #sql

Вопрос:

У меня есть такой сценарий:

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

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

Я хочу найти, ГДЕ m.module_content похож на любой из имеющихся у меня терминов, но он должен сверяться с ними всеми.

 SELECT m.module_termid, t.term_name, m.module_name, m.module_content
FROM modules m
JOIN terms t ON m.module_termid = t.term_id
WHERE m.module_content LIKE  '%' || (SELECT term_name FROM terms) ||  '%'
  

module_content содержит текст в формате html, поэтому в конечном итоге все, что мне нужно будет сделать, это, если он соответствует термину, и это еще не ссылки, я добавлю ссылку на этот конкретный термин.

Что здесь лучше всего сделать? (Я использую mysql btw)

Чтобы дать вам пример ожидаемого результата:

Термины: id: 1, имя: привет Модули: id: 1, содержимое: < p > Привет, мир < /p >

Я бы хотел, чтобы отображались модули с идентификатором 1, поскольку он содержит содержимое, которое где-то имеет термин «привет»

Обновлено:

Попробовал решение Пабло, но вот что происходит:

введите описание изображения здесь

Например, «Рэй Дэвис» не имеет ничего общего с термином «Float», так что это не должно было появиться.

Ответ №1:

Я думаю, вам просто нужно изменить свое JOIN условие на что-то вроде:

 SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  JOIN terms t ON (m.module_content LIKE  '%' || t.term_name ||  '%')
  

Сказав это, это может быть потенциально очень неэффективно. Рассмотрите возможность использования ПОЛНОТЕКСТОВОГО ИНДЕКСА ВМЕСТО этой операции.

Комментарии:

1. Я думаю, что это дает декартово произведение

2. Это не полное декартово произведение. Это соединение при условии, которое будет генерировать NxM строк… И ваше условие соединения должно быть таким, каким вы хотите: все строки, в которых есть термин в terms таблице внутри module_content .

3. Вы правы, в идеале это то, что у меня было бы. Посмотрите на пример ответа, который появился (обратите внимание, что Courtesy Double Up — это термин, а <p> Ray Davis </p> — это содержимое, и это не должно было появиться, если имя термина не Ray Davis: 4 Любезно удваивайте людей, которые не понимают плавающий <p> лучДэвис.</p>

4. Я обновил описание вашим предложением и сказал, почему оно не сработало.

Ответ №2:

После небольшого исследования мое решение будет выглядеть следующим образом:

 SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  INNER JOIN terms t ON m.module_termid = t.term_id
  WHERE m.module_content LIKE CONCAT('%', TRIM(t.term_name), '%')
  

редактировать: что касается комментария Пола Моргана, я заменил CONCAT('%', t.term_name, '%') на CONCAT('%', TRIM(t.term_name), '%') so, чтобы все пробелы в t.term_name были удалены. Если вам нужны пробелы в t.term_name, просто удалите TRIM вызов и используйте старую версию ( CONCAT('%', t.term_name, '%') )

Комментарии:

1. 1 но вам нужно обрезать t.term_name внутри CONCAT, чтобы все работало правильно. Если вы этого не сделаете, вам также потребуются любые конечные пробелы в t.term_name.

Ответ №3:

В MySQL нет оператора конкатенации, и запрос фактически должен быть записан как:

 SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  JOIN terms t ON m.module_content LIKE CONCAT('%', t.term_name, '%');
  

Но что произошло:

 m.module_content LIKE  '%' || t.term_name ||  '%'
  

фактически эквивалентно

 (m.module_content LIKE  '%') || (t.term_name) ||  ('%')
  

которое всегда равно 1. Таким образом, у вас есть декартово произведение =)

UPD: скорее как ссылка на меня, в MySQL есть оператор конкатенации || , но для его использования необходимо установить режим PIPES_AS_CONCAT:

 mysql> SET sql_mode= 'pipes_as_concat';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT 'qwe' || 'asd';
 ---------------- 
| 'qwe' || 'asd' |
 ---------------- 
| qweasd         |
 ---------------- 
1 row in set (0.00 sec)
  

Ответ №4:

Вы можете попробовать это вместо:

 SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  JOIN terms t ON (m.module_content LIKE  '%'   t.term_name    '%')
  

Ответ №5:

Вместо «LIKE», использование «IN» должно быть решением: что-то вроде:-

ВЫБЕРИТЕ m.module_termid, т.term_name, м.module_name, м.module_content
ИЗ модулей m ПРИСОЕДИНИТЕ термины t К m.module_termid = т.term_id
, ГДЕ m.module_content В (ВЫБЕРИТЕ term_name ИЗ terms);

Ответ №6:

Попробуйте следующий запрос —

 SELECT 
    tp.module_termid, 
    tp.term_name, 
    tp.module_name,
    tp.module_content  
FROM (
        SELECT 
            m.module_termid, 
            t.term_name, 
            m.module_name, 
            m.module_content,
            IF(LOCATE(t.term_name,m.module_content)!=0, m.module_content, ' ') 
                as required_content 
        FROM modules m 
        LEFT JOIN terms t ON m.module_termid = t.term_id
     ) tp 
WHERE tp.required_content != '';
  

Для приведенного выше запроса вы получите все строки, в которых данные столбцов term_name представлены в виде целого слова в столбце module_content таблицы module_content. Если вы не хотите сопоставлять только целое слово, то в этом случае вы можете использовать функцию регулярных выражений MYSQL вместо функции LOCATE .

Документацию для функции LOCATE можно найти здесь

Ответ №7:

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

  1. инвертировать индекс содержимого модуля.
  2. поиск популярных слов по индексу.
  3. привяжите идентификатор модуля к ключевому слову.

как вы можете see.it является очень эффективным и fast.so , проблема в том, как сделать инвертированный индекс для содержимого модуля.sphinx сделает хорошую работу. надеюсь, это вам поможет 🙂