Fórum Consulta aproximada (tipo google, forum, etc...) #337512
07/02/2007
0
componentes de acesso usados: dbx
precisaria fazer uma consulta em um determinado campo da tabela que:
1. não diferencie letras maiusculas de minusculas
2. vamos supor que eu queira realizar uma consulta no campo ´sinopse´ da tabela ´livros´, e vamos supor tambem que um dos registros desse campo seja: [b:decd4dc69f]´entao joao subiu no pé de feijao e sumiu´[/b:decd4dc69f]
Gostaria que tanto se eu digitasse no edit da consulta: ´joao subiu´ como eu digitasse: ´subiu joao´, esse registro fosse encontrado, ou seja uma pesquisa tipo a do google, a do forum aqui, etc...
alguem tem alguma dica de por onde posso começar?
Abraços!
Mahdak
Curtir tópico
+ 0Posts
08/02/2007
Weber
Gostei + 0
09/02/2007
Mahdak
sim, mas se eu fizer isso creio que ainda não vá funcionar... vamos ao exemplo:
1. frase digitada no edit1.text: ´forum clube delphi´
2. palavras identificadas e inseridas uma a uma em uma tabela.cds: ´forum´, ´clube´, ´delphi´
3. vamos supor que o unico registro no banco que contem o que eu queira encontrar está assim: ´no forum clube delphi voce encontra o que busca´, ou seja a frase digitada, esta contida dentro do regitro da tabela, porem misturada...
4. no SqlDataSet: ´select * from tabela where campo like ´+ edit1.text;
5. resultado da consulta := nada
Obs, eu precisaria que essa consulta retornasse aquele unico registro no caso. Refletindo, eu vi que da de fazer isso pegando registro a registro da tabela e fazendo a separação das palavras desse registro em uma tabela .cds e comparando com as palavras do edit, porem minha tabela é extensa e cada campo é um varchar(1000)...
alguma uma outra solução para isso???
um forte abraço!
Gostei + 0
09/02/2007
Emerson Nascimento
creio que a dica do Weber funciona:
(pressupondo que você já separou as palavras do edit num array ou num stringlist)
- se vc quiser que tenha TODAS AS PALAVRAS, independente da ordem:
instrucao := ´select * from tabela where ´; for i := 0 to high(arraydepalavras) do begin if i > 0 then instrucao := instrucao + ´ and ´; instrucao := instrucao + ´campo like ´+quotedstr(´¬´+arraydepalavras[i]+´¬´); end;
- se vc quiser que tenha QUALQUER UMA DAS PALAVRAS, troque o [b:a809ff264f]and[/b:a809ff264f] por [b:a809ff264f]or[/b:a809ff264f].
Gostei + 0
09/02/2007
Mahdak
instrucao := ´select * from tabela where ´; for i := 0 to high(arraydepalavras) do begin if i > 0 then instrucao := instrucao + ´ and ´; instrucao := instrucao + ´campo like ´+quotedstr(´¬´+arraydepalavras[i]+´¬´); end;
O irmão beleza! só a nivel de informação meu sistema é multi-camadas... onde tudo é parametrizado... nao envio sql ao servidor, entao consegui resolver assim:
no SqlDataSet do meu servidor de aplicação eu tenho:
select * from tabela where campo LIKE :Parametro
no aplicativo cliente(onde está o clientDataSet das palavras) eu tenho algo como:
cdsTermos.First; Dm.cdsTabela.First; while not cdsTermos.Eof do begin DM.Connection.Open; try DM.cdsTabela.Close; DM.cdsTabela.Params[0].AsString := ´¬´ + cdsTermosTERMO.AsString + ´¬´; DM.cdsTabela.Open; finally DM.Connection.Close; end; cdsTermos.Next; end;
muito obrigado emerson, sua dica foi imprescindivel para eu conseguir solucionar esse pobreeeema...
abração!!!
Gostei + 0
09/02/2007
Emerson Nascimento
eu também trabalho com n-camadas com acesso remoto de vários lugares do país para o servidor em São Paulo e, ao meu ver, um código assim:
if BuscaTodasAsPalavras then Condicao := ´ and ´ else Condicao := ´ or ´; instrucao := ´select * from tabela where ´; for i := 0 to high(arraydepalavras) do begin if i > 0 then instrucao := instrucao + Condicao; instrucao := instrucao + ´campo like ´+quotedstr(´¬´+arraydepalavras[i]+´¬´); end; DM.Connection.Open; try DM.cdsTabela.Close; DM.cdsTabela.CommandText := instrucao; DM.cdsTabela.Open; [faça o que tem q fazer] finally DM.Connection.Close; end;
seria bem mais rápido, pois a conexão com o banco seria feita apenas 1 vez e os dados trazidos de uma única vez, evitando queda na performance e tráfego de rede desnecessário (seja rede local ou internet).
Gostei + 0
09/02/2007
Mahdak
posso estar terrivelmente enganado, mas se eu tiver o minimo de razao nessa lógica, nao teria mais por que eu usar essa arquitetura multi-camadas, poderia apenas usar uma camada simples...
por favor, me corrija se eu estiver enganado brother...
ahh e outra coisa... cade a função Lower do Firebird 1.5.3 ???
dei um [b:527a305dae]´select * from tabela where Lower(campo) LIKE :Parametro´[/b:527a305dae] e olha o erro que me foi retornado:
DataBase Server Error: Function Unknow lower
saberias me dizer o que pode estar acontecendo?
abraços!
Gostei + 0
09/02/2007
Emerson Nascimento
mas da forma que eu passei acontecerá o conceito de n-camadas:
você envia a instrução, o provider pega essa instrução, executa no servidor e te devolve o resultado. n-camadas clássico.
quanto à falta da Lower(), não sei te dizer o que houve.
Gostei + 0
12/02/2007
Mahdak
sql := ´select * from NBR10004_2004_RES where ´; for i := 0 to cdsTermosR.RecordCount do begin if i > 0 then sql := sql + ´ AND ´; sql := sql + ´RP like ´+quotedstr(´¬´+cdsTermosRTERMO.Value[i]+´¬´); end;
fiz uma gambiarra com o seu código como pode-se notar acima... e nao deu certo por que eu to viajando naquela ideia do while ainda...
vamos supor que no campo TERMO do cdsTermosR, houvessem 2 registros, que poderiam ser por exemplo: ´clube´, ´delphi´
o retorno do código acima atualmente é:
select * from NBR10004_2004_RES where RP like ´¬delphi¬´ AND RP like ´¬delphi¬´ AND RP like ´¬delphi¬´
quando deveria ser:
select * from NBR10004_2004_RES where RP like ´¬clube¬´ AND RP like ´¬delphi¬´
pode me ajudar com isso???
um abração
Gostei + 0
13/02/2007
Mahdak
cdsTermosR.Last; sql := ´select * from NBR10004_2004_RES where ´; for i := 1 to cdsTermosR.RecordCount do begin if i > 0 then sql := sql + ´ AND ´; sql := sql + ´RP like ´+quotedstr(´¬´+cdsTermosRTERMO.AsString+´¬´); cdsTermosR.Prior; end;
[]´s
Gostei + 0
13/02/2007
Emerson Nascimento
(para localizar todos os termos. note que a condição [i:0e74e4de03]AND[/i:0e74e4de03] está ´engessada´)
sql := ´select * from NBR10004_2004_RES where ´; cdsTermosR.First; while not cdsTermosR.Eof do begin if cdsTermosR.Recno > 1 then sql := sql + ´ AND ´; sql := sql + ´RP like ´+quotedstr(´¬´+cdsTermosRTERMO.AsString+´¬´); cdsTermosR.Next; end;
ou você pode permitir a busca por ao menos um dos termos, fazendo assim:
if Checkbox_BuscaTodosOsTermos.Checked then Condicao := ´ AND ´ else Condicao := ´ OR ´; sql := ´select * from NBR10004_2004_RES where ´; cdsTermosR.First; while not cdsTermosR.Eof do begin if cdsTermosR.Recno > 1 then sql := sql + Condicao; sql := sql + ´RP like ´+quotedstr(´¬´+cdsTermosRTERMO.AsString+´¬´); cdsTermosR.Next; end;
desta forma quem está efetuando a consulta decide como quer a busca
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)