Search System - Select within another

Asked

Viewed 1,679 times

5

Hi, I’m running a search engine, but I’m kind of a layman when it comes to querys. The method I thought to refine the search, which in this case would be a simple search between two fields of a table with several products, was to go eliminating through selects.

$varBusca = str_replace(array(',',' ','.','%','-','/','\\'),'-',$_POST['busca']);
$varBusca = explode('-',$varBusca);
/*  metodo 1 */
$query_busca="";
$pos_busca=0;
foreach($varBusca as $chave)
{
    if ($pos_busca==0){
        $query_busca.="SELECT * FROM ( # ) WHERE pro_nome LIKE '%$chave%' OR pro_descricao LIKE '%$chave%'";
    }else{
        $query_inserida="SELECT * FROM ( # ) WHERE pro_nome LIKE '%$chave%' OR pro_descricao LIKE '%$chave%'";
        $query_busca=str_replace('#',$query_inserida,$query_busca);
    }
    $pos_busca++;
}
$query_busca=str_replace('#','produtos',$query_busca);
echo $query_busca;

I break the search string and search for every word. But this query ends up returning me no table item, even if there is some item with some query word.

Any suggestions?

  • Why do you wear the ( # )? Wasn’t it easier to name the table in question? Besides, it seems to me querys are the same. I didn’t really understand what you mean by this code.

  • @Jorgeb. apparently did not understand my code... I take the value of an input field (search box) and break to get the separate words. I want to take from the table only those items that contain all the words typed, regardless of the order... then put a select inside another select. I automatically add... but I’ve solved it. I’ve only had to use aliases. Name select as a temporary table.

2 answers

7


I adapted this solution from a another answer from me. The idea is to use PHP to divide your search into separate words, and generate the WHERE clause for you, but in a way that you already have a query that searches all the words at once:

<?php

   $pesquisa = str_replace( array( ',', '.', '%', '-', '/', '\\' ),' ', $_POST['busca'] );
   $palavras = explode( ' ', $pesquisa ); // dividindo as palavras pelo espaço
   $palavras = array_filter($palavras); // eliminando ítens vazios

   $query = 'SELECT * FROM produtos ';
   $cola = 'WHERE ';

   //Aqui você pode juntar vários campos no concat.
   $campo = 'CONCAT( pro_nome, " ", pro_descricao)';

   foreach ($palavras as $palavra) {
      $palavra = trim($palavra); //Removendo espaços em branco
      $palavra = mysql_real_escape_string($palavra); //Precisa da conexao com o banco!
      $query .= $cola.campo.' LIKE "%'.$palavra.'%" ';
      $cola = 'AND ';
   }

   echo htmlentities( $query );
?>

And the result when searching lápis azul 3b will be:

SELECT * FROM produtos WHERE
   CONCAT( pro_nome, " ", pro_descricao) LIKE "%lápis%" AND
   CONCAT( pro_nome, " ", pro_descricao) LIKE "%azul%" AND
   CONCAT( pro_nome, " ", pro_descricao) LIKE "%3b%"

(line breaks added for easy reading)

This way the search will find all these results:

Lápis azul 3b
Lápis 3b azul-claro
Lápis azulado 3bcd

Note that although some lines do not have exact results, it is better to have more things than the user does not find what they need. Keep in mind, however, that the price you pay for complexity is a slightly slower search.

  • I do not know much the sql functions, according to the need I will learn and this CONCAT is really very useful, thanks for the help!

  • 1

    Thanks Bacco. I had to use your code in a system that I am improving here and helped me a lot. I just had to convert to ASP.

  • You can improve with an order by e case // order by ( (case when pro_descricao) LIKE "%pencil%" then 1 Else 0 end)+case when pro_descricao) LIKE "%blue%" then 1 Else 0 end)+case when pro_descricao) LIKE "%3b%then" 1 Else 0 end)

  • @Motta I even do something like that in some situations. Boolean in My can already be used as numeric, so just (a LIKE '%a%') + ( b LIKE '%b%') ... to rank. Mysql would still have the IF( expressao, resultadoseverdadeiro, resultadosefalso) to shorten syntax in more complex cases. In Sqlite becomes more interesting because you can make a "virtual column' with the scoreboard and use in WHERE column > 0. I need to edit the post and comment on FTS anytime, because if it’s too complicated, the overhead of this lot of like ends up getting expensive and FTS can be an alternative.

1

I don’t know if I understand what you’re looking for.

You have a search field, where a user can type "Any text in the field" and in the search you want to bring all records that in a given field contains one of the field words ("One", "text", "any", "no", "field")?

If that’s it, you can do it like this:

$search = explodes(" ", $_POST["search"]);

$strSQL = "SELECT * FROM tabela";

foreach ( $search as $key => $value ){

    if ( $key == 0 ){
        $strSQL .= " WHERE ";
    }else{
        $strSQL .= " OR ";
    }

    $strSQL .= "campo like '%{$value}%'";

}

thus, assuming that the text typed in the search field is "Any text in the field", the value of the variable $strSQL will be:

SELECT * FROM tabela WHERE campo like '%Um%' OR campo like '%texto%' OR campo like '%qualquer%' OR campo like '%no%' OR campo like '%campo%'
  • I returned the solution that was already in use, which was already ready and is more complex, and covers the case of the search being in more than one field, as the author mentioned. However you took my +1 for having already answered before giving a correct initial path.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.