Как реализовать поиск по ключевым словам в MySQL?

27

Я новичок в программировании SQL.

У меня есть таблица, где поля id, position, category, location, salary range, description, refno.

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

Это запрос, который я пробовал, но он состоит из множества повторяющихся строк:

SELECT
    a.*,
    b.catname
FROM
    job a,
    category b
WHERE
    a.catid = b.catid AND
    a.jobsalrange = '15001-20000' AND
    a.jobloc = 'Berkshire' AND
    a.jobpos LIKE '%sales%' OR
    a.jobloc LIKE '%sales%' OR
    a.jobsal LIKE '%sales%' OR
    a.jobref LIKE '%sales%' OR
    a.jobemail LIKE '%sales%' OR
    a.jobsalrange LIKE '%sales%' OR
    b.catname LIKE '%sales%'
Теги:
search

7 ответов

40
Лучший ответ

Для одного ключевого слова в полях VARCHAR вы можете использовать LIKE:

SELECT id, category, location
FROM table
WHERE
(
    category LIKE '%keyword%'
    OR location LIKE '%keyword%'
)

Для описания вы обычно лучше добавляете полный текстовый индекс и выполняете Полнотекстовый поиск (только MyISAM):

SELECT id, description
FROM table
WHERE MATCH (description) AGAINST('keyword1 keyword2')
  • 0
    Выберите. *, b.catname ОТ задания a, категория b ГДЕ a.catid = b.catid AND a.jobsalrange = '15001-20000' AND a.jobloc = 'Berkshire' AND a.jobpos КАК '% sales%' ИЛИ a. jobloc LIKE "% sales%" ИЛИ a.jobsal LIKE "% sales%" ИЛИ a.jobref LIKE "% sales%" ИЛИ a.jobemail LIKE "% sales%" ИЛИ a.jobsalrange LIKE "% sales%" ИЛИ b. catname LIKE '% sales%' фактически, это запрос, который я пробовал, но он состоит из множества повторяющихся строк.
  • 3
    Вам просто нужно заключить в скобки ваши OR: ГДЕ a = b И c = d AND (e LIKE F OR g LIKE i)
Показать ещё 2 комментария
7
SELECT 
    *
FROM 
    yourtable
WHERE 
    id LIKE '%keyword%' 
    OR position LIKE '%keyword%'
    OR category LIKE '%keyword%'
    OR location LIKE '%keyword%'
    OR description LIKE '%keyword%'
    OR refno LIKE '%keyword%';
  • 0
    Выберите. *, b.catname ОТ задания a, категория b ГДЕ a.catid = b.catid AND a.jobsalrange = '15001-20000' AND a.jobloc = 'Berkshire' AND a.jobpos КАК '% sales%' ИЛИ a. jobloc LIKE "% sales%" ИЛИ a.jobsal LIKE "% sales%" ИЛИ a.jobref LIKE "% sales%" ИЛИ a.jobemail LIKE "% sales%" ИЛИ a.jobsalrange LIKE "% sales%" ИЛИ b. catname LIKE '% sales%' фактически, это запрос, который я пробовал, но он состоит из множества повторяющихся строк.
  • 0
    У вас есть несколько записей в таблице b с одной и той же катиде?
Показать ещё 1 комментарий
5

Вы можете найти еще один более простой вариант в теме: Match Against.. с более подробной информацией в 11.9.2. Булевые полнотекстовые поисковые запросы

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

Информация о том, как создавать индексы (MySQL): Индексирование и поиск MySQL FULLTEXT

В индексе FULLTEXT вы можете указать более одного столбца, результатом будет выражение SQL с индексом с именем search:

SELECT *,MATCH (`column`) AGAINST('+keyword1* +keyword2* +keyword3*') as relevance  FROM `documents`USE INDEX(search) WHERE MATCH (`column`) AGAINST('+keyword1* +keyword2* +keyword3*' IN BOOLEAN MODE) ORDER BY relevance;

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

В зависимости от ваших критериев вы можете использовать любые параметры.

5

Лично я не использовал бы сравнение строк LIKE в поле ID или в любом другом числовом поле. Для поиска ID # " 216" не имеет смысла возвращать 16 216, 216 51, 3 216 087, 53 216 68... и т.д. и т.д.; также с зарплатой.

Кроме того, если вы хотите использовать подготовленные инструкции для предотвращения инъекций SQL, вы должны использовать строку запроса, например:

SELECT * FROM job WHERE `position` LIKE CONCAT('%', ? ,'%') OR ...
5

В идеале, есть таблица ключевых слов, содержащая поля:

Keyword
Id
Count (possibly)

с индексом по ключевому слову. Создайте триггер insert/update/delete в другой таблице, чтобы при изменении строки каждое ключевое слово извлекалось и помещалось в (или заменялось) в этой таблице.

Вам также понадобится таблица слов, которая не будет считаться ключевыми словами (если и так, но...).

Таким образом, вы получите максимальную скорость для запросов, требующих поиска ключевых слов, и вы можете реализовать (относительно легко) более сложные запросы, такие как "содержит Java и RCA1802".

"LIKE" будут работать, но они также не будут масштабироваться.

4

Я объясню метод, который обычно предпочитает:

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

1) Добавьте поле (я обычно называю его "дайджест" ), где вы храните все данные из таблицы.

Поле будет выглядеть так:

"n-n1-n2-n3-n4-n5-n6-n7-n8-n9" и т.д., где n - одно слово

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

2) Используйте оператор LIKE% keyword% в поле дайджест:

SELECT * FROM table WHERE digest LIKE %keyword%

вы даже можете создать qUery с небольшим циклом, чтобы вы могли одновременно искать несколько ключевых слов:

SELECT * FROM table WHERE 
 digest LIKE %keyword1% AND 
 digest LIKE %keyword2% AND 
 digest LIKE %keyword3% ... 
  • 0
    Мне нравятся множественные операторы "LIKE" для ключевых слов.
  • 0
    Это решение выглядит более перспективным. Но как мне добиться лучших результатов в начале?
1

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

SELECT * FROM `landmarks` WHERE `landmark_name` OR `landmark_description` OR `landmark_address` LIKE '%keyword'
OR `landmark_name` OR `landmark_description` OR `landmark_address` LIKE 'keyword%' 
OR `landmark_name` OR `landmark_description` OR `landmark_address` LIKE '%keyword%'
  • 0
    Ну, насколько я знаю, самый поздний содержит все прежние.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню