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

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

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

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

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


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


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

3 ответа

Насколько я понимаю (и я также пишу против ужасной устаревшей базы данных), не существует такого понятия, как динамические предложения 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 превращает нуль в оценку идентичности, которая всегда верна и не влияет на предложение where.

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

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

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

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

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

Это то место, где работают такие инструменты, как Sphinx Search. Они создают индекс FULL TEXT для вашего "документа", а затем вы можете запросить sphinx, и он вернет вас назад, где в базе данных была найдена эта запись.

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

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

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

Другие вопросы по тегам