Необходим шаблон для динамического поиска по нескольким таблицам sql

Я ищу шаблон для выполнения динамического поиска по нескольким таблицам.

У меня нет контроля над устаревшей (и плохо спроектированной) структурой таблиц базы данных.

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

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


Да, поэтому я начал динамическое построение sql в коде. Кажется ужасным. Если я действительно пытаюсь поддерживать запрошенную возможность запрашивать любую комбинацию любого поля в любой таблице, это будет один МАССИВНЫЙ набор операторов if. дрожь


Думаю, я читал, что COALESCE работает только в том случае, если ваши данные не содержат NULL. Это верно? Если это так, не пойдем, так как у меня повсюду значения NULL.

Ответов (3)

Поиск и нормализация могут противоречить друг другу. Так что, вероятно, первым делом нужно получить какое-то «представление», которое показывает все поля, которые можно искать, в виде единой строки с одним ключом, дающим вам резюме. тогда вы можете добавить что-то вроде Lucene , чтобы получить полный текстовый индекс этих строк. Это работает так: вы запрашиваете «x» в этом представлении, и он возвращает вам ключ. Это отличное решение, рекомендованное самим Джоэлом в подкасте в течение первых 2 месяцев IIRC.

Насколько я понимаю (и я также являюсь тем, кто писал против ужасной устаревшей базы данных), не существует такой вещи, как динамические предложения WHERE. Это НЕ было решено.

Лично я предпочитаю генерировать динамический поиск в коде. Делает тестирование удобным. Обратите внимание: когда вы создаете свои sql-запросы в коде, не объединяйте вводимые пользователем данные. Используйте свои @variables!

Единственная альтернатива - использовать оператор COALESCE. Допустим, у вас есть следующая таблица:

Users
-----------
Name nvarchar(20)
Nickname nvarchar(10)

и вы хотите выполнить поиск по имени или псевдониму. Следующий запрос сделает это:

SELECT Name, Nickname
FROM Users
WHERE
    Name = COALESCE(@name, Name) AND
    Nickname =  COALESCE(@nick, Nickname)

Если вы не хотите что-то искать, просто передайте ноль. Например, передача «brian» для @name и null для @nick приводит к оценке следующего запроса:

SELECT Name, Nickname
FROM Users
WHERE
    Name = 'brian' AND
    Nickname =  Nickname

Оператор coalesce превращает null в оценку идентичности, которая всегда истинна и не влияет на предложение where.

Вам нужно что-то вроде SphinxSearch (для MySQL) или Apache Lucene .

Как вы сказали в своем примере, давайте представим себе резюме, которое будет состоять из нескольких полей:

  • Пункт списка
  • Имя,
  • Адрес,
  • Образование (это может быть отдельный стол) или
  • Опыт работы (может вырасти до отдельной таблицы, где каждая строка представляет предыдущую работу)

Таким образом, поиск слова во всех этих полях с WHERE быстро превращается в очень длинный запрос с несколькими JOINS.

Вместо этого вы можете изменить свою систему ссылок и думать о Все резюме как о едином документе, и вы просто хотите искать в указанном документе.

Вот где работают такие инструменты, как Sphinx Search. Они создают ПОЛНЫЙ ТЕКСТОВЫЙ индекс вашего «документа», а затем вы можете запросить sphinx, и он вернет вам, где в базе данных была найдена эта запись.

Действительно хорошие результаты поиска.

Не беспокойтесь о том, что эти инструменты не являются частью вашей СУБД, это избавит вас от многих головных болей, если вы используете подходящую модель «Документы» вместо неправильной модели «ТАБЛИЦЫ» для этого приложения.