none
Busca composta RRS feed

  • Pergunta

  •  

    E ae Pessoal,

     

    Preciso fazer uma busca com 1 ou mais palavras.

     

    Alguma coisa assim :

     

    SELECT Id_Ativo, Nome, Simbolo FROM Tb001_Ativos

    WHERE Simbolo LIKE '%petr%'  or Simbolo LIKE '%vale%' order by Simbolo

     

    Mas o duro é que nunca sei quantas palavras o usuario vai digitar, acho que é como os buscadores fazem.

     

    Alguem pode dar uma ajuda.

     

    Valew

    segunda-feira, 11 de agosto de 2008 15:09

Respostas

  • O exemplo abaixo cria uma vriável com o comando like e grava em uma tabela temporária. Vc pode criar a query com "OR" mas acho que gerando um tabela temporária garante mais performance.

     

    A query abaixo poderá ser tranformada em sp basta passar o parâmetro @texto_procurado = 'petr,vale' separado por "," (virgulas) o que pode ser feito no aplicativo. Na query exemplo é feito um tipo de split (recupero cada parametro entra as "," e gera um EXEC.

     

    Code Snippet

    CREATE TABLE #TAB ( TEXTO VARCHAR(4000))
    INSERT INTO #TAB  ( TEXTO ) VALUES ('PETROBRAS')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('VALE')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('VILA')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('PARAOPEBA')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('PRETOLEO')

    CREATE  TABLE #RES ( TEXTO_RESUTADO VARCHAR(4000))

    DECLARE @TEXTO_PROCURADO VARCHAR(400),
            @FORMA VARCHAR(30),
            @COMANDO VARCHAR(4000),
      @DELIMITADOR VARCHAR(2)   
     
    --DEFINE QUE VAI SER O DELIMITADOR
    SET @DELIMITADOR = ','

    --DEFINE PARAMETRO DE ENTRADA
    SET @TEXTO_PROCURADO = 'PETR,VALE'

    IF LEN(@TEXTO_PROCURADO) > 0 SET @TEXTO_PROCURADO = @TEXTO_PROCURADO + @DELIMITADOR 

    --INICIA LOOP PARA EXTRAIR TEXTO PARA EFETUAR A ATUALZIAÇÃO
    WHILE LEN(RTRIM(LTRIM(@TEXTO_PROCURADO))) > 0
    BEGIN
        SET @COMANDO = 'INSERT INTO #RES (TEXTO_RESUTADO) SELECT TEXTO FROM #TAB WHERE TEXTO LIKE '
        SET @FORMA = RTRIM(LTRIM(SUBSTRING(@TEXTO_PROCURADO, 1, CHARINDEX(@DELIMITADOR, @TEXTO_PROCURADO) - 1)))
        SET @COMANDO = @COMANDO +  '''' + '%' + @FORMA  + '%'+ ''''

        EXEC (@COMANDO)
        PRINT (@COMANDO)

     SELECT @TEXTO_PROCURADO =
     SUBSTRING(@TEXTO_PROCURADO , CHARINDEX(@DELIMITADOR, @TEXTO_PROCURADO ) + 1, LEN(@TEXTO_PROCURADO ))

    END

    SELECT * FROM #RES

    DROP TABLE #TAB
    DROP TABLE #RES


     

     

     

     

    segunda-feira, 11 de agosto de 2008 16:40

Todas as Respostas

  • O exemplo abaixo cria uma vriável com o comando like e grava em uma tabela temporária. Vc pode criar a query com "OR" mas acho que gerando um tabela temporária garante mais performance.

     

    A query abaixo poderá ser tranformada em sp basta passar o parâmetro @texto_procurado = 'petr,vale' separado por "," (virgulas) o que pode ser feito no aplicativo. Na query exemplo é feito um tipo de split (recupero cada parametro entra as "," e gera um EXEC.

     

    Code Snippet

    CREATE TABLE #TAB ( TEXTO VARCHAR(4000))
    INSERT INTO #TAB  ( TEXTO ) VALUES ('PETROBRAS')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('VALE')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('VILA')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('PARAOPEBA')
    INSERT INTO #TAB  ( TEXTO ) VALUES ('PRETOLEO')

    CREATE  TABLE #RES ( TEXTO_RESUTADO VARCHAR(4000))

    DECLARE @TEXTO_PROCURADO VARCHAR(400),
            @FORMA VARCHAR(30),
            @COMANDO VARCHAR(4000),
      @DELIMITADOR VARCHAR(2)   
     
    --DEFINE QUE VAI SER O DELIMITADOR
    SET @DELIMITADOR = ','

    --DEFINE PARAMETRO DE ENTRADA
    SET @TEXTO_PROCURADO = 'PETR,VALE'

    IF LEN(@TEXTO_PROCURADO) > 0 SET @TEXTO_PROCURADO = @TEXTO_PROCURADO + @DELIMITADOR 

    --INICIA LOOP PARA EXTRAIR TEXTO PARA EFETUAR A ATUALZIAÇÃO
    WHILE LEN(RTRIM(LTRIM(@TEXTO_PROCURADO))) > 0
    BEGIN
        SET @COMANDO = 'INSERT INTO #RES (TEXTO_RESUTADO) SELECT TEXTO FROM #TAB WHERE TEXTO LIKE '
        SET @FORMA = RTRIM(LTRIM(SUBSTRING(@TEXTO_PROCURADO, 1, CHARINDEX(@DELIMITADOR, @TEXTO_PROCURADO) - 1)))
        SET @COMANDO = @COMANDO +  '''' + '%' + @FORMA  + '%'+ ''''

        EXEC (@COMANDO)
        PRINT (@COMANDO)

     SELECT @TEXTO_PROCURADO =
     SUBSTRING(@TEXTO_PROCURADO , CHARINDEX(@DELIMITADOR, @TEXTO_PROCURADO ) + 1, LEN(@TEXTO_PROCURADO ))

    END

    SELECT * FROM #RES

    DROP TABLE #TAB
    DROP TABLE #RES


     

     

     

     

    segunda-feira, 11 de agosto de 2008 16:40
  • Jothaz,

     

    Parabéns pelo exemplo, achei muito bom!!!

    segunda-feira, 11 de agosto de 2008 16:53
  •  

    Obrigado Junior!

     

    Foi a única idéia que tive para este post.

     

    Esta idéia do split quebra o maior galho!

     

    Agora têm o inconveniente de gerar uma query dinâmica o que para alguns DBA´s chega a ser blasfemo.

    segunda-feira, 11 de agosto de 2008 17:04
  • E ae jothaz, funcionou redondo, valew Smile

     

    Mas tem um porem.rs

     

    Não consigo botar o Exec dentro de uma Function neh? Queria criar uma function e ela retornasse o resultado, tem alguma outro meio de contornar esse exec?

     

    Valew

    segunda-feira, 11 de agosto de 2008 17:13
  • cara, certa vez fiz algo assim:

     

    If Exists(Select * From sysobjects Where name = 'fnVariavel')

    Drop Function fnVariavel

    GO

    Create Function fnVariavel(

    @String varchar(1000), @Separador Char(1)

    )

    Returns @Array Table(

    Valor varchar(1000)

    )

    As

    Begin

    If Patindex('%' + @Separador + '%', @String) = 0

    Insert Into @Array Values(Ltrim(Rtrim(@String)))

    Else

    Begin

    While Patindex('%' + @Separador + '%', @String) > 0

    Begin

    Insert Into @Array Values(Substring(Ltrim(Rtrim(@String)), 1, Patindex('%' + @Separador + '%', Ltrim(Rtrim(@String))) - 1))

    Set @String = Substring(@String, Patindex('%' + @Separador + '%', @String) + 1, Len(@String))

    End

    Insert Into @Array Values(Ltrim(Rtrim(@String)))

    End

    Return

    End

    GO

     

    Declare

    @CHAVE varchar(max), @COMM varchar(max), @SEQ int, @VALOR varchar(max), @LIMITE int

    Set @CHAVE = 'CHAVES PARA PESQUISA, BUSCA'

    Set @LIMITE = (Select Count(valor) From fnVariavel(@CHAVE,','))

    Set @COMM = 'Select CAMPO From TABELA Where '

    Declare Cur Cursor For Select Row_Number() Over (Order By Valor) As Seq, Valor From fnVariavel(@CHAVE, ',')

    Open Cur

    Fetch Next From Cur Into @SEQ, @VALOR

    While @@Fetch_Status = 0

    Begin

    Set @COMM = @COMM + 'CAMPO Like ''%' + @VALOR + '%'' '

    If @SEQ < @LIMITE

    Begin

    Set @COMM = @COMM + 'OR '

    End

    Fetch Next From Cur Into @SEQ, @VALOR

    End

    Close Cur

    Deallocate Cur

    Set @COMM = @COMM + 'Order By CAMPO'

    Exec(@COMM)

     

    claro, onde tem CAMPO e TABELA, trocar pelo nome do campo e tabela pesquisada... não sei se ajuda

    segunda-feira, 11 de agosto de 2008 18:54
  • Bom Dia,

     

    Os scripts em TSQL estão bem criativos e de fato são capazes de retornar o esperado. Para uma tabela de títulos do mercado financeiro esse tipo de construção é suficiente (somando ações e opções não teríamos seqüer 10.000 papéis para pesquisar).

     

    No entanto para volumes de dados maiores (ou até para uma construção mais clara), considere utilizar o FULL TEXT INDEX. Sua consulta poderia ser facilmente escrita da seguinte forma:

     

    Code Snippet

    SELECT Papel

    FROM Ativos

    WHERE CONTAINS(Papel, ' "PETR" OR "VALE" ')

    GO

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 12 de agosto de 2008 12:01