Есть строка фильтра. Пользователь вводит в нее часть имени или фамилии или отчества, отображается список частичных совпадений, пользователь вводит польностью фимилию Иванов, отображаются Ивановы, далее он ставит пробел и вводит С, поиск должен найти всех Ивановых, чьи имена или отчества начинаются на С.
В список не должны попадать фамилии на С., в БД ФИО хранятся отдельными полями. Как привильнее всего построить текст запроса? Я разбивал строку на слова и для каждого слова я добавлял условия, получалось следующее:
SELECT *
FROM users
WHERE (name ILIKE word1 OR surname ILIKE word1 OR patronymic ILIKE word1)
AND (name ILIKE word2 OR surname ILIKE word2 OR patronymic ILIKE word2)
AND (name ILIKE word3 OR surname ILIKE word3 OR patronymic ILIKE word3)
Ответ
А почему вы не хотите фамилии на С ? Если считать, что пользователь вводит сначала имя Иван, а потом вводит букву С было бы логично показать Ивана Сидорова, а Сидора Иванова наверное не надо. А если он вводит две буквы, то уже начинать искать ? как ему найти "Гевара Че" ?
Предлагаю такую логику: пока слово одно - ищем его во всех трех полях по частичному совпадению. Но возможно надо ограничить минимальный размер слова, если оно из одной буквы, то боюсь результатов слишком много будет. Если слов более одного - то первое слово ищем во всех полях по точному совпадению, а остальные слова - то частичному совпадению.
Запрос, реализующий вышеуказанную логику:
select distinct users.*
from
(
select split_part(S,' ',N.column1) w1,split_part(S,' ',N.column2) w2,
split_part(S,' ',N.column3) w3,
substr('%%',2-N.column1/2) p1,substr('%%',2-N.column2/2) p2,
substr('%%',2-N.column3/2) p3,(rtrim(S) like '% _')::int+1 np
from (values(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,2,1),(3,1,2)) N,
(select Cast('Пушкин А С' as varchar) S) S
) A
join users
on name LIKE w1||substr(p1,np,1)
and surname LIKE w2||substr(p2,np,1)
and patronymic LIKE w3||substr(p3,np,1)
Единственный параметр передаваемый в запрос - ваша строка "Пушкин С А". Перед передачей строки из нее надо удалить лишние пробелы, т.е. слова должны быть разделены строго одним пробелом. Если нужен регистронезависимый поиск - приведите строку к нужному регистру в самом запросе
По работе запроса: цифры в подзапросе N - весь набор расположения слов. w1-w3 - выделенные компоненты из строки, согласно номерам в N. p1-p3 - один % для первого слова строки, и %% для остальных. np - признак поиска полного соответствия (когда слов более 1). substr в самом низу по этому признаку берут или не берут % для like.
Комментариев нет:
Отправить комментарий