Consulta por trechos de texto

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
Avatar do usuário
Marciel
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 158
Registrado em: Qui, 03 Mai 2007 10:12 am
Localização: Vitória - ES
Sabe qual o cúmulo da ignorância, da apatia e da ira?
Não sei, não quero saber e tenho raiva de quem sabe.

Bom dia,

Tenho uma tabela com um campo com o nome completo de pessoas. Tenho a seguinte SQL para consulta:

Selecionar tudo

SELECT * FROM PESSOAS WHERE NOME LIKE '%' || REPLACE(:FILTRO, ' ', '%') || '%';
Assim o usuário pode digitar "JOSÉ SILV" e resultados semelhantes retornarão, como "JOSÉ DA SILVA" e "PAULO JOSÉ SILVEIRA".

Agora a situação que preciso: Buscar com o texto: "JOSÉ MARIA" e retornar todos os nomes que contenham as duas palavras da string, em qualquer ordem, como "JOSÉ ANTONIO MARIA" e "MARIA JOSÉ".

Tem algum recurso de SQL do Oracle que me ajude nisso?
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

Fiz um exemplo rápido sem testar muito, se puder verificar melhor por gentileza, seria isso:

Selecionar tudo

SQL> create table pessoa as
  2  select 'JOSÉ ANTONIO MARIA' nome from dual union all
  3  select 'MARIA JOSÉ' from dual union all
  4  select 'MARIANA JOSÉ' from dual union all
  5  select 'JOSÉ' from dual union all
  6  select 'LUCAS' from dual union all
  7  select 'MARIA' from dual;
 
Table created
SQL> with t as (
  2  select 'JOSÉ MARIA' filtro from dual
  3  ) -- fim do filtro
  4  select p.nome
  5    from pessoa p
  6   where not exists (select 1
  7                       from (select regexp_substr(filtro, '\S+', 1, level) nome
  8                               from t
  9                             connect by regexp_substr(filtro, '\S+', 1, level) is not null) f
 10                      where regexp_instr(p.nome, '([^[:alpha:]]|^)' ||f.nome || '([^[:alpha:]]|$)') = 0);
 
NOME
------------------
JOSÉ ANTONIO MARIA
MARIA JOSÉ
O recurso usado é chamado de expressões regulares, tem mais informações aqui:
http://docs.oracle.com/cd/E11882_01/app ... regexp.htm

Basicamente a lógica é repartir a string do filtro em palavras separadas por espaço, tratar essas palavras como se fossem uma tabela e fazer uma pesquisa que peça por todos nomes de pessoas onde não exista (not exists) nenhuma dessas palavras ausentes.
Avatar do usuário
fbifabio
Moderador
Moderador
Mensagens: 199
Registrado em: Ter, 22 Fev 2011 1:51 pm
Localização: São Paulo - SP
Contato:
Fábio Prado
www.fabioprado.net

Pessoal,

Tenho um artigo em meu blog onde comento sobre expressões regulares, para aqueles que quiserem obter mais informações sobre o assunto:

http://www.fabioprado.net/2010/10/expre ... lares.html

[]s

Fábio Prado
www.fabioprado.net
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 15 visitantes