К сожалению, я не думаю, что для вашей проблемы есть чисто SQL-решение.Вот пара альтернатив:
- Динамический SQL - создайте запрос, который включает только операторы предложения WHERE для значений, которые фактически предоставлены.Предполагая, что средний поиск фактически заполняет только 2-3 поля, индексы можно добавлять и использовать.
- Полнотекстовый поиск - перейдите к чему-то более похожему на поиск по ключевым словам Google.Нет индивидуальных опций.
- Lucene (или что-то еще) - Поиск вне SQL;Это довольно существенное изменение.
Еще один вариант, который я только что вспомнил, когда внедрял в систему.Создайте вертикальную таблицу, которая включает в себя все данные, по которым вы ищете, и создайте для них запрос.Это проще всего сделать с динамическим SQL, но это можно сделать с помощью Table Value Parameters или временной таблицы в крайнем случае.
Идея состоит в том, чтобы создать таблицу, которая выглядит примерно так:
- Идентификатор профиля
- Имя атрибута
- Значение атрибута
Таблица должна иметь уникальный индекс (идентификатор профиля, имя атрибута) (уникальный для созданияпоиск работает правильно, индекс сделает его работоспособным).
В этой таблице у вас будут строки данных, такие как:
- (1, 'city', 'grand rapids')
- (1, «штат», «MI»)
- (2, «город», «Детройт»)
- (2, «штат», «MI»')
Тогда ваш SQL будет выглядеть примерно так:
SELECT *
FROM Profile
JOIN (
SELECT ProfileID
FROM ProfileAttributes
WHERE (AttributeName = 'city' AND AttributeValue = 'grand rapids')
AND (AttributeName = 'state' AND AttributeValue = 'MI')
GROUP BY ProfileID
HAVING COUNT(*) = 2
) SelectedProfiles ON Profile.ProfileID = SelectedProfiles.ProfileID
... -- Add your paging here
Как я уже сказал, вы можете использовать временную таблицу с именем / значениями атрибута:
SELECT *
FROM Profile
JOIN (
SELECT ProfileID
FROM ProfileAttributes
JOIN PassedInAttributeTable ON ProfileAttributes.AttributeName = PassedInAttributeTable.AttributeName
AND ProfileAttributes.AttributeValue = PassedInAttributeTable.AttributeValue
GROUP BY ProfileID
HAVING COUNT(*) = CountOfRowsInPassedInAttributeTable -- calculate or pass in
) SelectedProfiles ON Profile.ProfileID = SelectedProfiles.ProfileID
... -- Add your paging here
Насколько я помню, это получилось очень хорошо, даже для довольно сложных запросов (хотя я думаю, что у нас было только 12 или около того столбцов).