Search Query not works Properly : Php Like Query - php

<?php
include"configration.php";
?>
<?php
$query = $_GET['query'];
$min_length = 1;
//echo $query;exit();
if (strlen($query) >= $min_length) { // if query length is more or equal minimum length then
//echo "success";exit();
$query = htmlspecialchars($query);
$query = mysqli_real_escape_string($conn, $query);
$sql = "SELECT * FROM table2
WHERE title LIKE '%".$query."%' order by date DESC";
$raw_results = mysqli_query($conn, $sql) or die(mysql_error());
if (mysqli_num_rows($raw_results) > 0) { // if one or more rows are returned do following
while ($res = mysqli_fetch_array($raw_results)) { ?>
<?php echo $res['title'] ?> // Place where result comes ..
<?php }
}
}
?>
This is code works fine but search in this way
For Example Title is: you are vary nice boy but lazy
When I search by:
You are vary ............. result shows ..
vary nice boy ............. result shows ..
vary lazy, or boy lazy or vary lazy .. result not shows ..
Plz some one help me in this and how to show searched query in title ..
<title> Searched Query ...</title>

LIKE '%boy lazy%' will show the Of the cases where anything can be before boy lazy and anything can be after boy lazy, but boy lazy will be together.
In your case, one approach can be, you can explode your $query, and then use multiple LIKE queries to create sql query. Example:
<?php
//$conn = mysqli_connect("localhost","your user","your pass","db");
$query = $_GET['query'];
$min_length = 1;
//echo $query;exit();
if (strlen($query) >= $min_length) { // if query length is more or equal minimum length then
//echo "success";exit();
$query = htmlspecialchars($query);
$query = mysqli_real_escape_string($conn, $query);
$searchKeys = explode(' ',$query);
$sql = "SELECT * from table2 where title ";
foreach ($searchKeys as $key) {
$sql.= "LIKE '%".$key."%' AND title ";
}
$sql = substr($sql, 0, -10);
//$sql.="ORDER BY date DESC;";
$raw_results = mysqli_query($conn, $sql) or die(mysql_error());
if (mysqli_num_rows($raw_results) > 0) { // if one or more rows are returned do following
while ($res = mysqli_fetch_assoc($raw_results)) {
echo $res['title']."\n";
}
}
}

When you search title LIKE "%vary lazy%", you will get records that contain the string "vary lazy" preceeded and followed by any other or no character sequences. If you want to match strings that contain the words - I should better say, the character sequences - "vary" and "lazy" in that specific order you should use:
title LIKE "%vary%lazy%"
However, this will also match "varylazy", "varying lazytown characters".
Assuming you generally intend to use queries as you mentioned, i.e. each word is separated by a space character and you want to see if those words appear in a text in specifically that order, you could write something like this:
$query = $_GET["query"];
$query = '%'.str_replace(' ', '%', $query).'%';
//... MySQL stuff
Please be aware that the code above is very specific to your needs. I wouldn't use it as a general purpose approach for processing query strings, e.g. having multiple spaces between words would result in multiple consequent % in your SQL query - I'm not even sure if that is allowed. However, under the constraints described, this code should work just fine.

Related

SQL get all possible results using separators

I have database with list of similar words. I need to get similar words and I am trying this approach to get every similar word:
I am using LIKE on mysql query to get similar words.
It's not enough to use LIKE, so I make every possible string with % to get more similar results. I don't know and I can't find if there is any LIKE alternative to find much more relevant queries.
So for example to find similar words like "EL", I am using this query:
SELECT * FROM `words` WHERE word LIKE 'el' OR word LIKE '%el' OR word LIKE '%el%' OR word LIKE '%e%l%'
And it returns only one result, which is not what I want to. However if I would use multi_query and multiple queries like:
SELECT * FROM `words` WHERE word LIKE 'el';
SELECT * FROM `words` WHERE word LIKE '%el';
SELECT * FROM `words` WHERE word LIKE '%el%';
SELECT * FROM `words` WHERE word LIKE '%e%l%';
To fetch these I use:
if ($con->multi_query($query)) {
do {
/* almacenar primer juego de resultados */
if ($result = $con->store_result()) {
while ($row = $result->fetch_row()) {
printf("%s\n", $row[0]);
}
$result->free();
}
/* mostrar divisor */
if ($con->more_results()) {
printf("-----------------\n");
}
} while ($con->next_result());
}
/* cerrar conexión */
$con->close();
These are (example/similar) results I get with it:
el,espinel,el,wheels,espinel,wheels
It would get all the possible results. Of course I would need to filter the duplicates, but I would get them all.
For single query I use:
$result = $con->query($query);
$row = mysqli_fetch_row($result);
However I think multiple queries and filtering would take more time then single query, so I am looking for a way to get all the results on single query or even better without creating all possible variations of string.
As mentioned already, you only need to run the last query. In order to get the desired order of the results (relevance), you'd need to implement that logic via php.
$keyword = 'Your search term';
function getRelevance($value,$keyword){
$value = strtolower($value);
$keyword = strtolower($keyword);
$index = strpos($value, $keyword);
$word_index = strpos($value, ' '.$keyword);
if($index==0) // first word starts with keyword
return 3;
else if($word_index!==false) // any word starts with keyword
return 2;
else if($index!==false) // keyword matches anywhere
return 1;
else
return 0;
}
$keyword = mysqli_real_escape_string($con, $keyword); // prevent SQL injection
$res = $con->query("SELECT * FROM words WHERE `word` LIKE '%$keyword%'");
$words = array();
while($line = $res->fetch_assoc()){
$line['relevance'] = getRelevance($line['word'],$keyword); // assign relevance value based on the "el" query and the elements word
$words[] = $line;
}
function compareRelevance($a,$b){
return $b['relevance'] - $a['relevance'];
}
usort($words,'compareRelevance');
This will fetch all matching entries from the 'words' table and sort them based on the search term.

Is there a way to use SQL query that would return results if values can be in any order?

My code let me perform search, as long as the order of the words is correct.
Let's say I'm searching for big dog, but I also want to search for dog big. It get more complicated with 3 or more words.
Is there a way to create a SQL query which would let me search through values with any order?
Only way I can think of this is by having multiple queries, where I change order of PHP variables manually...
<?php
if(isset($_GET['query']) && !empty($_GET['query'])) {
$query = $_GET['query'];
$query_array = explode(' ', $query);
$query_string = '';
$query_counter = 1;
foreach($query_array as $word) {
$query_string .= '%' . $word . (count($query_string) == $query_counter++ ? '%' : '');
}
$query = "SELECT * FROM pages WHERE Name LIKE '$query_string'";
$result = sqlsrv_query($cms->conn, $query);
while($row = sqlsrv_fetch_array($result)) {
extract($row);
echo ''.$Name.'<br>';
}
sqlsrv_free_stmt($stmt);
}
else {
//echo 'NO GET';
}
?>
You could assemble your conditions and check for each word on it's own:
$query_array = explode(' ', $query);
$queryParts = array();
foreach ($query_arra AS $value){
$queryParts[]="Name like '%".mysql_real_escape_string($value)."%'";
}
$searchString = implode(" AND ", $queryParts);
The Search string would now be Name like '%big%' AND Name like '%dog%' ... depending on how much search-keywords have been there.
I use the same approach very often, also when it is required that ALL keywords appear in at least ONE of the columns. Then you need one more loop to create the required AND conditions:
$search = "Big Dog";
$keywords = explode (" ", $search);
$columns = array("Name", "description");
$andParts = array();
foreach ($keywords AS $keyword){
$orParts = array();
foreach($columns AS $column){
$orParts[] = $column . " LIKE '%" . mysql_real_escape_string($keyword) . "%'";
}
$andParts[]= "(" . implode($orParts, " OR ") . ")";
}
$and = implode ($andParts, " AND ");
echo $and;
this would produce the query part (Name like '%Big%' OR description like '%Big%') AND (Name like '%Dog%' or description like '%Dog%')
So, it will find any row, where dog and big are appearing in at least one of the columns name or description (could also be both in one column)
Since your original querystring is something like %big%dog%, so I assume you are okay with matching big wild dog. In this case, you can just use the AND operator.
(Name LIKE '%big%" and Name LIKE '%dog%")
myisam supports full text search:
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
One thing you could look into is Full Text Search for ms sql server.
https://msdn.microsoft.com/en-us/library/ms142571.aspx
it's similar to a "search engine" in that it works off of an algorithm to rank results and even similar words (think thesaurus type lookups)
It's not exactly trivial to set up, but it's easy enough to find a tutorial on the subject and how to query from FTS (as the syntax is different than say LIKE '%big%dog%')
Here's a sample query from the page linked above:
SELECT product_id
FROM products
WHERE CONTAINS(product_description, ”Snap Happy 100EZ” OR FORMSOF(THESAURUS,’Snap Happy’) OR ‘100EZ’)
AND product_cost < 200 ;

PHP MySQL query returning NULL

I have a MySQL table that looks like this:
index | tag | posts
-------------------------
1 | cats | 9,10
2 | a cat | 9,10
3 | kitty | 9,10
4 | meow | 9,10
I am trying to just return the row that matches a search query.
I passed the search parameter using a simple ?search=cats.
This is the PHP that I'm using:
$search = $_GET['search'];
$query = mysql_query("SELECT * FROM tags WHERE tag = '$search'");
echo(mysql_num_rows($query));
$result = mysql_fetch_array($query);
$print = $result['posts'];
echo($print);
However the mysql_num_rows($query) prints 0 and the $print returns NULL. I can check it with ($print == ""), it evaluates to TRUE and mysql_num_rows($query) returns 4.
I tried setting the search query to something that wasn't in the table and it retuned FALSE as expected. I also tried removing the WHERE tag = '$search' and it returns the table like it should.
Is there something I'm overlooking?
Edit
Took everyone's advice and the code I'm using now is:
$search = mysql_real_escape_string($_GET['search']);
var_dump($search); //prints string(4) "cats" just like it should
$queryText = "SELECT * FROM tags WHERE tag = '%".$search."%'";
echo($queryText); //SELECT * FROM tags WHERE tag = '%cats%'
$query = mysql_query($queryText) or die(mysql_error()); //no error
$rows = mysql_num_rows($query); //this returns 0 and I know it should match 1 row
echo('rows: '.$rows);
$result = mysql_fetch_array($query);
$print = $result['posts'];
echo($print); //empty
Still have the same problem. The mysql_query is retuning NULL instead of the row or FALSE if it doesn't match.
(in the future I will use the mysqli API, but I would like to finnish this project in mysql. thanks for your suggestions and advice)
Try this code now.
Remeber when you want to debug something in PHP the faster way is var_dump not echo. Also you should avoid mysql_api because they are deprecated, use PDO instead PDO on PHP.net
var_dump($_GET); // Just for debuggin if as something
$search = $_GET['search'];
$query = mysql_query("SELECT * FROM tags WHERE tag = '".mysql_real_escape_string($search)."'");
// echo(mysql_num_rows($query));
$result = mysql_fetch_array($query);
var_dump($result);
//$print = $result['posts'];
//echo($print);
Ok so after referring to the above edit you made, here is the solution
Use "LIKE" instead of "=" when using wildcard "%"
So your query now should be
$queryText = "SELECT * FROM tags WHERE tag LIKE '%" . $search . "%'";
[I created the exact same db on my local system and ran the same code you gave, After making the above changes, It runs as expected]
$search = $_GET['search'];
echo $select_query="SELECT * FROM tags WHERE tag = '".mysql_real_escape_string($search)."'";
$query = mysql_query($select_query);
echo(mysql_num_rows($query));
while($result = mysql_fetch_array($query))
{
print_r($result);
}
Note:
$search = $_GET['search'];
$query = mysql_query("SELECT * FROM tags WHERE tag = '$search'");
That is very dangerouse: It allow sql incersion code to your database. You must always escape all what you get from the client.
$search = mysql_real_escape_string($_GET['search']); //It require open database connection.
Note2:
mysql_query is obsolete, use mysqli instead ;-)
Answer:
If you have not answer, you probable has an error in an other part.
Try
//1) Look if your search has a correct value
var_dump($search);
//2) Replace the query with (just for debugging):
$query = mysql_query("SELECT * FROM tags WHERE tag = 'cats';");
You may also use "tag like '%cats%'" if you want a more flexible search.
If you remove the WHERE tage = '$search', it cannot return the table like it should because your mysql_fetch_array is not in a while loop... but that aside...
// make sure before you execute the code to check that $_GET['search'] is not empty
// start with escaping the search-value (for mysql-injection)
$search = msyql_real_escape_string($_GET['search']);
// changed the query so it searches for tags containing the search value.
// if you would have records with tags "blue cat" and "red cat" it shows them both
// when searching for "cat"
$query = mysql_query("SELECT * FROM tags WHERE tag LIKE '%".$search."%'");
// put the number of rows in a var
$num = mysql_num_rows($query);
// check this var if it's not 0
if ($num != '0'){
while ($row = mysql_fetch_array($query){
echo $row['posts'];
// etc...
}
} else {
// 0 rows found
echo "nothing found";
}

Advance Searching, PHP & MySQL

I'm trying to create an Advanced Searching form that sort of look like this ;
http://img805.imageshack.us/img805/7162/30989114.jpg
but what should I write for the query?
I know how to do it if there is only two text box but three, there's too many probability that user will do.
$query = "SELECT * FROM server WHERE ???";
What should I write for the "???"
I know how to use AND OR in the query but lets say if the user only fill two of the textbox and one empty. If I write something like this ;
$query = "SELECT * FROM server WHERE model='".$model."' and brand='".$brand."' and SN='".$SN.'" ";
The result will return as empty set. I want the user can choose whether to fill one,two or three of the criteria. If I use OR, the result will not be accurate because if Model have two data with the same name (For example :M4000) but different brand (For example : IBM and SUN). If I use OR and the user wants to search M4000 and SUN, it will display both of the M4000. That's why it is not accurate.
If the user can decide how many criteria he wants to enter for your search and you want to combine those criteria (only those actually filled by the user), then you must dynamically create your SQL query to include only those fields in the search that are filled by the user. I'll give you an example.
The code for a simple search form could look like this:
$search_fields = Array(
// field name => label
'model' => 'Model',
'serialNum' => 'Serial Number',
'brand' => 'Brand Name'
);
echo "<form method=\"POST\">";
foreach ($search_fields as $field => $label) {
echo "$label: <input name=\"search[$field]\"><br>";
}
echo "<input type=\"submit\">";
echo "</form>";
And the code for an actual search like this:
if (isset($_POST['search']) && is_array($_POST['search'])) {
// escape against SQL injection
$search = array_filter($_POST['search'], 'mysql_real_escape_string');
// build SQL
$search_parts = array();
foreach ($search as $field => $value) {
if ($value) {
$search_parts[] = "$field LIKE '%$value%'";
}
}
$sql = "SELECT * FROM table WHERE " . implode(' AND ', $search_parts);
// do query here
}
else {
echo "please enter some search criteria!";
}
In the above code we dynamically build the SQL string to do a search ("AND") for only the criteria entered.
Try this code
<?php
$model="";
$brand="";
$serialNum="";
$model=mysql_real_escape_string($_POST['model']);
$brand=mysql_real_escape_string($_POST['brand']);
$serialNum=mysql_real_escape_string($_POST['serialNum']);
$query=" select * from server";
$where_str=" where ";
if($model == "" && $brand == "" && $serialNum == "")
{
rtrim($where_str, " whrere ");
}
else
{
if($model != "")
{
$where_str.= " model like '%$model%' AND ";
}
if($brand != "")
{
$where_str.= " brand like '%$brand%' AND ";
}
if($serialNum != "")
{
$where_str.= " serialNum like '%$serialNum%' AND ";
}
rtrim($where_str, " AND ");
}
$query.= $where_str;
$records=mysql_query($query);
?>
For those framiliar with mysql, it offers the ability to search by regular expressions (posix style). I needed an advanced way of searching in php, and my backend was mysql, so this was the logical choice. Problem is, how do I build a whole mysql query based on the input? Here's the type of queries I wanted to be able to process:
exact word matches
sub-string matches (I was doing this with like "%WORD%")
exclude via sub-string match
exclude via exact word match
A simple regexp query looks like:
select * from TABLE where ROW regexp '[[:<:]]bla[[:>:]]' and ROW
regexp 'foo';
This will look for an exact match of the string "bla", meaning not as a sub-string, and then match the sub-string "foo" somewhere.
So first off, items 1 and 4 are exact word matches and I want to be able to do this by surrounding the word with quotes. Let's set our necessary variables and then do a match on quotes:
$newq = $query; # $query is the raw query string
$qlevel = 0;
$curquery = "select * from TABLE where "; # the beginning of the query
$doneg = 0;
preg_match_all("/\"([^\"]*)\"/i", $query, $m);
$c = count($m[0]);
for ($i = 0; $i < $c; $i++) {
$temp = $m[1][$i]; # $temp is whats inside the quotes
Then I want to be able to exclude words, and the user should be able to do this by starting the word with a dash (-), and for exact word matches this has to be inside the quotes. The second match is to get rid of the - in front of the query.
if (ereg("^-", $temp)) {
$pc = preg_match("/-([^-]*)/i", $m[1][$i], $dm);
if ($pc) {
$temp = $dm[1];
}
$doneg++;
}
Now we will set $temp to the posix compliant exact match, then build this part of the mysql query.
$temp = "[[:<:]]".$temp."[[:>:]]";
if ($qlevel) $curquery .= "and "; # are we nested?
$curquery .= "ROW "; # the mysql row we are searching in
if ($doneg) $curquery .= "not "; # if dash in front, do not
$curquery .= "regexp ".quote_smart($temp)." ";
$qlevel++;
$doneg = 0;
$newq = ereg_replace($m[0][$i], "", $newq);
}
The variable $newq has the rest of the search string, minus everything in quotes, so whatever remains are sub-string search items falling under 2 and 3. Now we can go through what is left and basically do the same thing as above.
$s = preg_split("/\s+/", $newq, -1, PREG_SPLIT_NO_EMPTY); #whitespaces
for ($i = 0; $i < count($s); $i++) {
if (ereg("^-", $s[$i])) { # exclude
sscanf($s[$i], "-%s", $temp); # this is poor
$s[$i] = $temp;
$doneg++;
}
if ($qlevel) $curquery .= "and ";
$curquery .= "ROW "; # the mysql row we are searching in
if ($doneg) $curquery .= "not ";
$curquery .= "regexp ".quote_smart($s[$i])." ";
$qlevel++;
$doneg = 0;
}
# use $curquery here in database
The variable $curquery now contains our built mysql query. You will notice the use of quote_smart in here, this is a mysql best practice from php.net. It's the only mention of security anywhere in this code. You will need to run your own checking against the input to make sure there are no bad characters, mine only allows alpha-numerics and a few others. DO NOT use this code as is without first fixing that.
You have to provide $model, $brand, $serial which come from your search-form.
$query = "SELECT * FROM `TABLE` WHERE `model` LIKE '%$model%' AND `brand` LIKE '%$brand%' AND `serial` LIKE '%$serial%'";
Also take a look at the mysql doc
http://dev.mysql.com/doc/refman/5.1/en/string-comparison-functions.html
A basic search would work like this:
"SELECT * FROM server WHERE column_name1 LIKE '%keyword1%' AND column_name2 LIKE '%keyword2%' .....";
This would be case for matching all parameters.For matching any one of the criteria, change ANDs to ORs

error on query , trying to make a search by keywords

i have a variable and an user_name i want to search on a string(function_description) of the user_name for it
whats wrong with this :
$function_keywords = mysql_real_escape_string($_POST['function_keywords']);
if($function_keywords=="" || empty($function_keywords)){
redirect("show.php?functions=PHP");
}
//trim whitespace from the stored variable
$trimmed = trim($function_keywords);
//separate key-phrases into keywords
$trimmed_keywords = explode(" ",$trimmed);
// Build SQL Query for each keyword entered
foreach ($trimmed_keywords as $trimm){
// MySQL "MATCH" is used for full-text searching.
//this code is ebv weird , should check out soon!
$query = "SELECT *
FROM functions
WHERE isEnabled=1 AND isPrivate=0
AND function_description LIKE '{$trimm}'
AND user_name='{$user_name}'
";
// Execute the query to get number of rows that contain search kewords
$results=mysql_query ($query,$connection);
as far as "like" syntax goes you have to use the '%' symbol. if you query for
select * from table where column like '%yourkeyword%'
then it returns any rows with 'yourkeyword' inside the table column.
your statement will be true only if the column = 'yourkeyword'
That's highly inefficient. If someone puts in 5 keywords, you'd be running the search 5 times and getting 5 sets of results. Try something more along these lines:
$words = $_POST['function_keywords'];
if ($words == '') {
... abort ...
}
$parts = trim(explode(' ', $words));
$clauses = array();
foreach($parts as $part) {
$clauses[] = "function_description LIKE '%" . mysql_real_escape_string($part) . "%'";
}
$clause = implode(' OR ' , $clauses);
$sql = "SELECT .... WHERE (isEnabled=1) AND (isPrivate=1) AND (user_name='$user_name') AND ($clause)";
$result = mysql_query($sql) or die(mysql_error());
This'll build up a long series of or statements for each keyword specified, and run the whole thing as a single query.
To see if the function_description contains the keyword you need to use '%' which stands for anything much the way '*' does in unix. Try function_description LIKE '%{$trimm}%'

Categories