Нужен шаблон для динамического поиска нескольких таблиц SQL - PullRequest
7 голосов
/ 13 августа 2008

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

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

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

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


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


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

Ответы [ 3 ]

5 голосов
/ 13 августа 2008

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

1 голос
/ 04 июля 2009

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

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

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

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

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

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

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

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

1 голос
/ 13 августа 2008

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

...