Foreach mysql select result - php

I want to create a search field like if I search "Spinach, Watermelon", it will explode the input by ",", and run MySQL search database. That means the SQL will run as
SELECT * FROM table
WHERE vegetable LIKE '%Spinach%' OR fruits LIKE '%Spinach%'
SELECT * FROM table
WHERE vegetable LIKE '%Watermelon%' OR fruits LIKE '%Watermelon%'
My database table data looks something like this :
id Vegetable fruits
----------------------
1 Spinach Apple
2 Cucumber Orange
3 Spinach Watermelon
The result of each id only can come out once.
<php>
$keywords = trim($_REQUEST['keyword']);
$keyword = explode(",", $keywords);
foreach($keyword as $keys=>$select)
{
$sql = "SELECT * FROM table WHERE vegetable LIKE '%keyword %' OR fruits LIKE '%keyword %'";
$result = mysqli_query($conn, $sql);
while ($rs = mysqli_fetch_array($result))
{
$vege = $rs["vegetable"];
$fruits = $rs["fruits"];
}
}
<html>
<form method=post>
<input type="text" class="form-control" placeholder="SEARCH..." value="<?=$keywords?>">
</form>
</html>

If you are open to using REGEXP with an alternation instead of LIKE, then here is a straightforward approach:
$keywords = trim($_REQUEST['keyword']);
$keywords = preg_replace("/,\s*/", "|", $keywords);
$where = "[[:<:]](" . $keywords . ")[[:>:]]";
$sql = "SELECT * FROM table ";
$sql .= "WHERE vegetable REGEXP '" . $where . "' OR fruits REGEXP '" . $where . "'";
$result = mysqli_query($conn, $sql);
while ($rs = mysqli_fetch_array($result)) {
$vege = $rs["vegetable"];
$fruits = $rs["fruits"];
}
Assuming you passed in the keywords search string "Spinach, Watermelon", the above script would generate this query:
SELECT *
FROM table
WHERE
vegetable REGEXP '[[:<:]](Spinach|Watermelon)[[:>:]]' OR
fruits REGEXP '[[:<:]](Spinach|Watermelon)[[:>:]]';
Honestly the best approach here would be to use LIKE or REGEXP with a prepared statement. If you do choose to use my approach, then you absolutely should sterilize the incoming CSV string to make sure it has only alphanumeric characters, comma, and whitespace in it.

Hitting database in for loop is not a good approach, You can build you query like this:
<?php
$keywords = trim($_REQUEST['keyword']);
$keyword = explode(",", $keywords);
$sqlWhere = '';
foreach($keyword as $keys=>$select)
{
$sqlWhere .= "LIKE '%$select%' OR";
}
$sqlWhere = rtrim($sqlWhere, "OR");
$sql = "SELECT * FROM table " . $sqlWhere;
$result = mysqli_query($conn, $sql);
while ($rs = mysqli_fetch_array($result))
{
$vege = $rs["vegetable"];
$fruits = $rs["fruits"];
}
?>

Try this, It will print your records must.
<php>
$keywords = trim($_REQUEST['keyword']);
$keyword = explode(",", $keywords);
for($i=0; $i<count($keyword); $i++)
{
$sql = "SELECT * FROM table WHERE vegetable LIKE '%" . $keyword[$i] . "%' OR fruits LIKE '%" . " . $keyword[$i] . " . "%'";
$result = mysqli_query($conn, $sql);
$rs = mysqli_fetch_array($result);
echo "<pre>"; print_r($rs); exit;
}
?>
<html>
<form method=post>
<input type="text" class="form-control" placeholder="SEARCH..." value="<?=$keywords?>">
</form>
</html>

I think your probelm is "*The result of each id only can come out once.".
So better make one Query:
$keywords = trim($_REQUEST['keyword']);
$keyword = explode(",", $keywords);
$where = [];
foreach($keyword as $keys)
{
$where[] = "vegetable LIKE '%".$keys." %' OR fruits LIKE '%".$keys." %'";
}
$sql = "SELECT * FROM table ".(empty($where) ? '' : implode(' OR ', $where));
so you have one query an one result set.
Dont forgett to escape your keywords.

Related

Regular Expression mysql with AND operator

I had create a search field and if i search "Spinach, Watermelon", it will explode the input by ",", and run MySQL search database. That means the SQL will run as
SELECT * FROM table WHERE
(vegetable LIKE '%Spinach%' OR fruits LIKE '%Spinach%') AND (vegetable LIKE '%Watermelon%' OR fruits LIKE '%Watermelon%')
My database table data looks something like this :
id Vegetable fruits
----------------------
1 Spinach Apple
2 Cucumber Orange
3 Spinach Watermelon
The result of each id only can come out once.
<php>
$keywords = trim($_REQUEST['keyword']);
$keywords = preg_replace("/,\s*/", "|", $keyword);
$where = "[[:<:]](" . $keywords . ")[[:>:]]";
$sql = "SELECT * FROM table ";
$sql .= "WHERE vegetable REGEXP '" . $where . "' OR fruits REGEXP '" . $where . "'";
$result = mysqli_query($conn, $sql);
while ($rs = mysqli_fetch_array($result))
{
$vege = $rs["vegetable"];
$fruits = $rs["fruits"];
}
</php>
<html>
<form method=post>
<input type="text" class="form-control" placeholder="SEARCH..." value="<?=$keywords?>">
</form>
</html>
Here is the literal MySQL query using REGEXP:
SELECT *
FROM table
WHERE
(vegetable REGEXP '[[:<:]]Spinach[[:>:]]' OR fruits REGEXP '[[:<:]]Spinach[[:>:]]') AND
(vegetable REGEXP '[[:<:]]Watermelon[[:>:]]' OR fruits REGEXP '[[:<:]]Watermelon[[:>:]]');

Search for different tables with multiple words

I have a form
<form action="buscar.php" method="GET">
<input type="text" name="q" />
</form>
And my page where they show the results
<?php
require_once 'meekrodb.php';
$q = $_GET['q'];
$results = DB::query("SELECT * FROM product_description WHERE description like '%$q%'");
foreach ($results as $row) {
echo $row['name']."<br>";
}
?>
For example I have these phrases in description:
My car is big and green
My house is small and green
When I look for green, the 2 results come out, but if I look for a green house nothing comes out.
The problem is that I have to search for continuous text to work for example... My house is small...
How can I improve this query? Thank you
Try to explode GET variable.Or you can try to play with CONCAT
Explode
$q = $_GET['q'];
$word_array = explode(" ",$q);
$sqlnames="SELECT * FROM product_description WHERE";
$count = 0;
foreach($word_array as $value){
if($count == 0){
$sqlnames .= " description LIKE '" . $value ."'";
}
else{
$sqlnames .= " OR description LIKE '" . $value ."'";
}
$count = 1;
$sqlnames .= " OR description LIKE '" . $value ."'";
}
$sqlnames .="LIMIT 20";
CONCAT
(something like that)
$results = DB::query("SELECT * FROM product_description WHERE description LIKE '%$q%' OR description LIKE '%$q%' OR CONCAT(description, ' ', description ) LIKE '%$q%' LIMIT 20");
I have not tested this, but you can try to play.

how to perform a multi sql search via php in one field

i am using this sql search to find a title and artist in my database. I have on field containing infos like "ref.1570 title artist.mp4". When I do the search it works but in one direction only, i would like to get the result whatever the order i do the search... to be more precise if i search "title artist" no problem i found it. If i search "artist title" no way ... how can you help me making php sql search both directions ?
Best regards and thank you for your help.
Phil
i am using this code :
if ($search != null) {
$sql = 'SELECT * FROM `catalog` WHERE (`file`LIKE "%' . $search . '%")';
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE (`file`LIKE "%' . $search . '%")';
}
Why don't you split keyword $search with space and append with Like statement in the query. Eg:
if ($search != null) {
$keywords=explode(" ",$search);
$sql = 'SELECT * FROM `catalog` WHERE 1=1'; // just to append OR condition.This won't affect anything as the condition will always be true.
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE 1=1 ';
foreach($keywords as $key){
if(!empty($key)){
$sql.=' And file Like \'%'.$key.'\%';
$sqlCount.=' And file Like \'%'.$key.'\%';
}
}
}
I believe this will work as you expected.
I think you won't get around a foreach:
if ($search != null) {
$arrayOfSearchTerms = explode(' ', $search);
$sql = 'SELECT * FROM `catalog` WHERE ';
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE ';
$termNumber = 0;
foreach ($arrayOfSearchTerms as $term) {
$addingSql = '';
if ($termNumber > 0) {
$addingSql = ' OR ';
}
$addingSql .= '(`file` LIKE "%') . $term . '%")';
$sql .= $addingSql;
$sqlCount = $addingSql;
$termNumber++;
}
}
You need to iterate over your search terms and add this terms into your 'LIKE'-Statement
you can try this research: it does a LIKE %word% for every word. If you want more powerfull research you should use tools like elasticsearch etc...
This way you could do:
$parts = explode(" ",$search)
$queryParts = array();
foreach ($parts as $part) {
$queryParts[] = `artist`LIKE "%' . $part . '%" ;
}
// this way we can have like %artist% AND like %title%
$querySearch= implode(" AND ", $queryParts);
$sql = 'SELECT * FROM `catalog` WHERE (". $querySearch .")';
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE (`". $querySearch .")';
you have solved my problem i know now hos to correctly explode a request into variables ..
$search = $name;
$explode=explode(" ",$search);
print_r (explode(" ",$explode));
and then i use my sql request like this
$sql = 'SELECT * FROM `catalog` WHERE (`idc` LIKE "%' . $search . '%" OR `file` LIKE "%' . $search . '%" OR `title` LIKE "%' . $explode[0] . '%" AND `artist`LIKE "%' . $explode[1] . '% " OR `artist`LIKE "%' . $explode[0] . '%" AND `title`LIKE "%' . $explode[1] . '%")';
and it is working !
COOL
Use the multi query functions,
in mysqli should be : mysqli_multi_query();
More info on : Mysqli Multiquery

How can I scan all my fields in MySQL for form input

In my script below, the user inputs a form and rows are returned from a MYSQL table if rows are similar to inputted by the user. I am building a search engine and everything is based on rank. But I want to be able to adjust the code below to see how many times the word 'iPad' for example comes up with the row fields, which are 'title', 'description', 'keywords' and 'link'. If so, I want that row to return higher than say a row that has a higher id, but only mentions iPad once in all of the fields combined.
My code is below:
Terms together query:
$query = " SELECT * FROM scan WHERE ";
$terms = array_map('mysql_real_escape_string', $terms);
$i = 0;
foreach ($terms as $each) {
if ($i++ !== 0){
$query .= " AND ";
}
$query .= "title LIKE '%{$each}%' OR link LIKE '%{$each}%' OR keywords LIKE '%{$each}%' OR description LIKE '%{$each}%' ";
}
$query = mysql_query($query) or die('MySQL Query Error: ' . mysql_error( $connect ));
echo '<p class="time">Qlick showed your results in ' . number_format($secs,2) . ' seconds.</p>';
$numrows = mysql_num_rows($query);
if ($numrows > 0) {
while ($row = mysql_fetch_assoc($query)) {
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
$rank = $row['rank'];
Seperate Terms Query
$query = " SELECT * FROM scan WHERE ";
$terms = array_map('mysql_real_escape_string', $terms);
$i = 0;
foreach ($terms as $each) {
if ($i++ !== 0){
$query .= " OR ";
}
$query .= "title LIKE '%{$each}%' OR link LIKE '%{$each}%' OR keywords LIKE '%{$each}%' OR description LIKE '%{$each}%' ";
}
// Don't append the ORDER BY until after the loop
$query = mysql_query($query) or die('MySQL Query Error: ' . mysql_error( $connect ));
$numrows = mysql_num_rows($query);
if ($numrows > 0) {
while ($row = mysql_fetch_assoc($query)) {
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
$rank = $row['rank'];
I'd try to do this using an auxiliary field on which to run a FULLTEXT query, in which you would save all textual data:
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
The alternative is to run the filtering in MySQL and the ranking in PHP. You might squeeze some performance by running a single LIKE on the concatenated field.
By the way, your code above lacks parentheses in the LIKE, so that the results won't be correct: you mustn't ask WHERE field1 LIKE 'x' OR field2 LIKE 'x' AND field1 LIKE 'y' OR..., you must state WHERE (field1 LIKE 'x' OR field2 LIKE 'x') AND (field1 LIKE 'y' OR...).
// Here we search for ALL terms (all must be present at least once)
// use ' OR ' to ask that at least one term must be present once.
$where = array();
foreach($terms as $term)
$where[] = "( CONCAT(title,'|',link,'|',keywords) LIKE '%{$term}%')";
$query .= ' WHERE ' . '('.implode(' AND ', $where).')';
Now in the OR case you could do a simple ranking on the number of matched terms (with AND the number is always the total number of terms):
$select_fields[] '(' . implode ('+', $where) . ') AS ranking';
Otherwise in SQL you would need recourse to a really ugly hack:
(LENGTH(
REPLACE(CONCAT(title,'|',link,'|',keywords),'{$term}','')
) - LENGTH(CONCAT(title,'|',link,'|',keywords)))/LENGTH('{$term}');
This above calculates the difference between the total length of the text where the search is to be done and the total length of the same text, with search string removed. The difference is of course proportional to how many times the search string is there: if the string is 8 characters long, a difference of 32 would mean that it is present four times. Dividing the length difference by the length of the term, we obtain the number of hits.
The problem is that for several terms you have to complicate the query enormously, and it might be really expensive to run:
$select_fields = array('*');
$where = array();
$rank = array();
foreach($terms as $term)
{
// assume $term is NOT QUOTED
$search = mysql_real_escape_string($term);
$concat = "CONCAT(title,'|',link,'|',keywords)";
$where[] = "(${concat} LIKE '%{$search}%')";
$rank[] = "(LENGTH(REPLACE(${concat},'{$search}',''))
- LENGTH(${concat}))/LENGTH('{$search}')";
}
$select_fields[] = "(".implode(",", $rank).") AS ranking";
$query .= "SELECT " . implode(',', $select_fields)
. ' FROM scan WHERE (' . implode(' AND ', $where) . ')';

array_unique question

I have a search engine type website. It takes the users input, stores the query as $q, explodes the query and searches the database. It then displays the results with the name and web address of each result.
For example, if i searched for "computer programming"... Stack Overflow, stackoverflow.com would be my result. However, it displays twice. (once for computer, and once for programming.)
I tried to solve this with the array_unique function, and it does not work.
any help would be appreciated.
// trim whitespace
$trimmed = trim($q);
// seperate key-phrases
$trimmed_array = explode(" ", $trimmed);
// remove duplicates
$clean_array = array_unique($trimmed_array);
//query dataabase
foreach ($clean_array as $trimm){
$query = mysql_query("SELECT * FROM forumlist WHERE `keys` LIKE '%" . mysql_real_escape_string($trimm) . "%' ORDER BY rating DESC, total_ratings DESC") or die(mysql_error());
Thank you!
//query dataabase
$query = 'SELECT * FROM forumlist ';
$where = array();
foreach ($clean_array as $trimm){
$where[] = " `keys` LIKE '%" . mysql_real_escape_string($trimm) . "%' ";
}
if(!empty($where)){
$query .= " WHERE ". implode(' OR ', $where);
}
$query .= " ORDER BY rating DESC, total_ratings DESC";
$result = mysql_query($query) or die(mysql_error());

Categories