When I run my code I cannot retrieve the entry that I am targeting because the keywords that are being run through the query are not the same as the keywords in the database.
Keywords:
$keywords = 'spaghetti,macaroni,hamburger';
Query:
mysql_query("SELECT * FROM ---- WHERE keywords LIKE '%$keywords%' ORDER BY id DESC LIMIT 1");
I am targeting an entry with these keywords:
food, restaurant, hamburger, spaghetti, taco,pie
I may be missing something simple here since I've been working for 12 hours straight. However, I've had no luck with anything I've tried to do to work around this issue.
From my point of view the query should be returning the target entry since there are 2 matching keywords.
What should I be doing differently?
$like = array();
$keywords = explode(',' , $keywords);
foreach($keywords as $keyword) {
$like[] = "`keywords` LIKE '%$keyword%'";
}
$like = implode(' OR ', $like);
$query = "SELECT * FROM `table` WHERE $like ORDER BY id DESC LIMIT 1";
You need to break up the keywords and do a separate LIKE comparison for each one
SELECT * FROM mytable
WHERE keywords LIKE '%spaghetti%' OR keywords LIKE '%macaroni%'
-- ...
You could do something like this
<?php
$keywords = 'spaghetti,macaroni,hamburger';
$query = "SELECT * FROM mytable WHERE 1=1";
$keywords = explode(',', $keywords);
if (count($keywords)) {
$query .= sprintf(
" AND (%s)",
implode(' OR ', array_map(function($word){
return "keywords LIKE '%{$word}%'";
}, $keywords))
);
}
echo $query;
// SELECT * FROM mytable WHERE 1=1 AND (keywords LIKE '%spaghetti%' OR keywords LIKE '%macaroni%' OR keywords LIKE '%hamburger%')
As you can see from the comments, there are better ways to handle this, but I'm assuming that this rudimentary question is looking for a simple answer.
I'm not doing any input sanitization, or adding any other fail safes. Building queries like this is not very reliable and you should continue to learn about PHP/MySQL to avoid common pitfalls in the future. However, I believe more advanced approaches are a bit out of your reach at the moment. If someone else would like to provide better techniques that they think the OP can grasp, by all means, go for it :)
Storing multiple values as a CSV inside a column is a common SQL anti-pattern. It's hard to use and even harder to optimize:
How to fix the Comma Separated List of Doom
You have to use LIKE with separeted works, you can try this:
$keywords = 'spaghetti,macaroni,hamburger';
$arrayWords = explode(',', $keywords);
$like = '';
foreach($arrayWords as $word)
$like .= empty($like) ? " keywords LIKE '%$word%' " : " OR keywords LIKE '%$word%' ";
mysql_query("SELECT * FROM ---- WHERE $like ORDER BY id DESC LIMIT 1");
mysql_query("SELECT * FROM ---- WHERE keywords LIKE '%". implode("%' OR keywords LIKE '%", explode(",", $keywords)) ."%' ORDER BY id DESC LIMIT 1");
Try this, it may be faster than using multiple or clauses
Select * from mytable
where keywords REGEXP 'spaghetti|macaroni|hamburger'
Related
I have a script i want to search multiple tables how can i do that.
**Also add ORDER BY function in Mysql query **
help is appreciated.
if(isset($_GET["search"]))
{
$condition = '';
//$query = explode(" ", $_GET["search"]);
$query = explode(" ", $_GET["search"]);
foreach($query as $text)
{
$condition .= "title LIKE +'%".mysqli_real_escape_string($connect, $text)."%' OR ";
}
$condition = substr($condition, 0, -4);
$sql_query = "SELECT * FROM countries WHERE " . $condition;
$result = mysqli_query($connect, $sql_query);
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
echo '<tr><td>'.$row["title"].'</td></tr>';
}
}
else
{
echo '<label>Data not Found</label>';
}
}
SELECT * FROM (
(SELECT title FROM countries WHERE title LIKE '%mystring%')
UNION
(SELECT title FROM locations WHERE title LIKE '%mystring%')
) ta
That's the sql, but would need to point out the drawbacks of using union as a search tool.
a) The longer the tables get the longer the search will get, you can add in Limits on each query and then on the union as a whole - but it's not a winner.
b) The table columns have to match up so you'll need perhaps to do myID as ID, then you will need an extra column to say which each is (0=country, 1= location)
c) I guess you are trying to do a site search of sorts, in which case there isn't a relevance in this instance.
Hence I would use something like http://sphinxsearch.com/ bit tricky to get started, but a really quick search engine. If you have a large site. Otherwise look into mysql full text searches which also have relevence and are built in so easier to get started with.
I am using the code below to search my database based on keywords given by the user. It seems to work fine for the most part, but i am searching both based on location and keywords. This is where I have the issues.
If i put no location in and search it returns all results regardless of location, which is fine. If i put in a location that does not exist and some keywords, It returns all results matching the keywords and seems to ignore the location.
Also if i leave the keywords empty and search by a location that does exist, it seem that it ignores the location again and just returns all results.
So it would seem my logic for setting the location is not working.
$keys = explode(" ",$tag);
$search_sql = "SELECT DISTINCT providers.* FROM providers JOIN provider_tags ON providers.id = provider_tags.provider_Id JOIN tags ON provider_tags.tag_id = tags.id WHERE tags.tag_name LIKE '%$tag%' OR providers.provider_name LIKE '%$tag%' OR providers.provider_contact_name LIKE '%$tag%' OR providers.provider_features LIKE '%$tag%' ";
foreach($keys as $k){
$search_sql .= " OR tags.tag_name LIKE '%$k%' OR providers.provider_name LIKE '%$k%' OR providers.provider_contact_name LIKE '%$k%' OR providers.provider_features LIKE '%$k%' ";
}
$search_sql .= " AND (providers.provider_town LIKE '%{$location}%' OR providers.provider_local_area LIKE '%{$location}%' OR providers.provider_postcode LIKE '%{$location}%')";
echo $search_sql;
$gettags = mysqli_query($con, $search_sql) or die(mysqli_error($con));
You are adding a bunch of OR conditions in a loop and then a big AND condition for the location. Your AND condition is checked with the last OR of the loop. If any of the others OR in the condition is true then you get a result no matters the AND condition.
Edit :
You'll probably get the results you want if you :
wrap every OR conditions with parenthesis;
wrap all the OR conditions together.
Something like :
$search_sql = "SELECT DISTINCT providers.* FROM providers JOIN provider_tags ON providers.id = provider_tags.provider_Id JOIN tags ON provider_tags.tag_id = tags.id WHERE ( (tags.tag_name LIKE '%$tag%' OR providers.provider_name LIKE '%$tag%' OR providers.provider_contact_name LIKE '%$tag%' OR providers.provider_features LIKE '%$tag%') ";
foreach($keys as $k){
$search_sql .= " OR (tags.tag_name LIKE '%$k%' OR providers.provider_name LIKE '%$k%' OR providers.provider_contact_name LIKE '%$k%' OR providers.provider_features LIKE '%$k%') ";
}
$search_sql .= ") AND (providers.provider_town LIKE '%{$location}%' OR providers.provider_local_area LIKE '%{$location}%' OR providers.provider_postcode LIKE '%{$location}%')";
I've researched this but couldn't find a solution for my specific problem.
I have a column containing data in a certain format. Here are some examples:
1
6
14
1;6;14;16
etc...
I need a mysql statement which for example it will select all columns where 16 occurs.
I've tried this but it's also selecting columns where 1 and 6 occur:
"SELECT * FROM tbl WHERE kategorien LIKE '%".$_GET['katid']."%' AND status = 1 ORDER BY pos ASC"
Thanks in advance for any help!
You can try creating a helper function like this:
// Helper function
function getLike($str, $deliminator = ';', $field = 'kategorien') {
if (false !== strpos($str, $deliminator)) {
$strParts = explode($deliminator, $str);
return "($field LIKE '%". implode("%' OR $field LIKE '%", $strParts) . "%')";
} else {
return "$field LIKE '%$str%'";
}
}
// Debug
var_dump(getLike('1;6;14;16'));
Outputs:
string '(kategorien LIKE '%1%' OR kategorien LIKE '%6%' OR kategorien LIKE '%14%' OR kategorien LIKE '%16%')' (length=100)
In your query, you'd use it like this:
"SELECT * FROM tbl WHERE ". getLike($_GET['katid']) ." AND status = 1 ORDER BY pos ASC"
You could use MySQL function FIND_IN_SET:
SELECT * FROM tbl
WHERE
FIND_IN_SET('16', REPLACE(kategorien, ';', ','))>0
however, it is usually not a good idea to store comma separated values in a single field, please have a look at this question: Is storing a delimited list in a database column really that bad?
$randomvariable=$_GET['randomvariable'];
$search="SELECT * from objects
WHERE transactiontype='$randomvariable'
order by id DESC";
Now if $randomvariable is empty (nothing), I would like it to return all rows. Currently if it's empty it returns nothing, because it basically searches for nothing from all of the rows.
$randomvariable = ESACPE_MYSQL_STRING($_GET['randomvariable']);
$search =
"SELECT * FROM objects " .
(empty($randomvariable) ? "" : "WHERE transactiontype='$randomvariable' ") .
"ORDER BY id DESC";
Where ESCAPE_MYSQL_STRING is the relevant function for escaping strings for whatever MySQL driver you're using.
Another, more modular way:
$search = array(
"select" => "SELECT * FROM objects",
"where" => "WHERE transactiontype='$randomvariable'",
"order" => "ORDER BY id DESC"
);
if (empty($randomvariable)) {
unset($search["where"]);
}
$search = implode(' ', $search);
The nice thing about this is that you can add, remove or alter the query for any situation easily, having easy access to any part of the query.
You could also do this with CASE() in SQL, but it's somewhat cumbersome and you shouldn't expect good performance either:
SELECT * FROM objects
WHERE transactiontype LIKE
CASE WHEN '$randomvariable' = '' THEN
'%'
ELSE
'$randomvariable'
END CASE
ORDER BY id DESC
Another approach:
if ($_GET['randomvariable'] != "") {
$where = "transactiontype = " . $randomvariable;
} else {
$where = "1";
}
$search = "SELECT * from objects WHERE " . $where . " ORDER BY id DESC";
Try as below
$randomvariable=mysql_real_escape_string($_GET['randomvariable']);
$where = '';
if($randomvariable){
$where .= "WHERE transactiontype='{$randomvariable}'";
}
$search="SELECT * from objects ".$where." order by id DESC";
There are some great answers here. I have one to add for a simple solution.
I sometimes run into this issue when I don't need a WHERE clause since none of my conditions to build my WHERE clause are met. A simple trick I like to use is something like this:
$sql_statement = "SELECT * FROM ".$table_names." WHERE 1 = 1 ";
if ($array) {
foreach ($array as $key => $value){
$sql_statement .= " AND ".$key." = '".$value."' ";
}
}
This way, you don't need any tricky logic or string manipulation because 1 always equals 1 in your WHERE clause and you can keep your looped string concats the same format. You can obvious extend this concept to do more, but for the purposes of this question, this psuedocode is just a simple way to achieve the goal.
You can use the IN operator to indicate many values for the WHERE clause and include all possible values for transactiontype as the default parameter.
Split it in 2 queries:
$randomvariable = $_GET['randomvariable'];
if($randomvariable)
$search="SELECT * from objects WHERE transactiontype='$randomvariable' order by id DESC";
else
$search="SELECT * from objects order by id DESC";
If you really need to do it in SQL and not in your language, you can do this:
$search="SELECT * from objects WHERE ("" = '$randomvariable' or transactiontype='$randomvariable') order by id DESC";
This will not perform well, however, and an IF/ELSE in your language should be preferred.
Add a simple if statement checking if $randomvariable is null. If it is then change the query to return all rows.
To cut a long story short: Is it possible and if it is - how can I build a query that looks somewhat like this one
SELECT * FROM a
WHERE row = 1 AND
(other_row LIKE '%..%' OR another_row LIKE '%..%')
Basically I cann't come up / find a solution to this problem. I just cann't seem to figure how to add the brackets to the activerecords query. Is that even possible?
My current code:
$data = $this->where('row', 1)
->like('another_row', '...')
->or_where('row', 1)
->like('other_row', $search)
->get('a')
->result();
Result:
SELECT * FROM (`a`) WHERE `row` = 1 OR `row` = 1 AND `another_row` LIKE '%...%' AND other_row` LIKE '%...%'
You can try this.
$query = $this->db->select('*')
->from('a')
->where('row',1)
->where("(other_row LIKE '%%' OR another_row LIKE '%%' )")
->get();
foreach ($query->result() as $row) {
//do sth.
}
You can write custom query string (from active record class)
Custom string:
You can write your own clauses manually:
$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);
I also having problem with or_where so i simply make my custom query like
$this->db->query("SELECT * FROM `a` WHERE `row`=1 AND (CONDITION1 OR CONDITION2)")
$sql= "SELECT * FROM `a`
WHERE row = '1' AND
(other_row LIKE '%" . $value . "%' OR another_row LIKE '%" . $value . "%')";
$this->db->query($sql);
Why dont you try this:
$this->db->where("row = 1 AND
(other_row LIKE '%..%' OR another_row LIKE '%..%')");
$this->db->get('a');
It's how you can write custom WHERE in CI. If it is not what u r looking for, feel free to explain
You can use the following:
$this->db->like('title', 'match', 'before');
It will produce:
WHERE `title` LIKE '%match' ESCAPE '!'
$this->db->where('salary_range_min >= ',$salarymin)
$this->db->where('salary_range_max <= ',$salarymax)
$this->db->where('job_title like '.$title.'% or skill like %'.$title.'%');
// OR */
$this->db->where('job_title like '.$title.'% or skill like %'.$title.'%',FALSE);
// OR */
$this->db->where('job_title like '.$title.'% or skill like %'.$title.'%',NULL);
Try this out