I am using a search box to find entries in my database.
One column contains the title / name of the thing being looked for.
Then I have a second column which gives a short description as applicable (few words usually)
I am trying to search (with the search box) to match either one or even both of the cells combined. Is that possible, and if yes, how?
You can see my code below which kind of shows what I try to achieve, but in any case, let me illustrate this a bit:
Example:
Database.title = "towel"
Database.description = "red, small"
Now, if I type into my search box "tow%red" I want to find the item.
It obviously does not find it, because the title does not contain "red". But if I search for "towel" only, it might show me different items based on different sizes, colors, or other attributes and the list becomes too long.
Of course I also want to be able to simply search for "%red%small% and still be able to find it, or just search for "towel".
Here is my php code that does the search:
if ( !isset($_REQUEST['term']) ) {
exit;
}
$search = mysql_real_escape_string($_REQUEST['term']);
$queryString = "SELECT * FROM items WHERE title+description LIKE '%{$search}%'";
$query = mysql_query($queryString);
$data = array();
if ( $query && mysql_num_rows($query) )
{
while( $row = mysql_fetch_array($query, MYSQL_ASSOC) )
{
$label = $row['title'];
if ($row['description']) {
$label .= ' — '. $row['description'];
}
$data[] = array(
'label' => $label,
'value' => $row['code']
);
}
}
echo json_encode($data);
flush();
I know the above is not going to work, I just put it that way to make clear what I want.
The working code contains this line instead:
$queryString = "SELECT * FROM items WHERE title LIKE '%{$search}%'";
Add a FULLTEXT (see documentation here) index to title and description.
ALTER TABLE items
ADD FULLTEXT INDEX items_index
(title, description);
This will let you search those colums.
Then build a query like this:
SELECT *
FROM items
WHERE MATCH(title, description)
AGAINST ('SEARCH KEYWORD HERE' IN BOOLEAN MODE);
I don't know if that would help you but
"SELECT * FROM items WHERE CONCAT(title, '', description) LIKE '%{$search}%'";
seems simple unless i'm missing something:
$queryString = "SELECT * FROM items WHERE title LIKE '%{$search}%' OR description LIKE '%{$search}%'";
have you tried this.....?
SELECT * FROM items WHERE `title` LIKE '%{$search}%' OR `description` LIKE '%{$search}%'
Related
I have a table in mysql that contain two columns or fields, one column is for an id_column and others for description of string type. I would like to insert an specific string to the column description.
For example:
insert into table_name (id, description) values ('1','we go to school')
And then in my php file, I would like to fetch the specific word "school" from the column description.
How can I do this?
You can use like with wildchar .
select * from your_table
where description like '%school%';
in php for find if a string contain a word you can use
$my_string = 'we go to school';
if (strpos($my_strong, 'school') !== false) {
echo 'string found';
}
I'm not really understand what you want. But I guess, you want to get image source from the description column.
$q = mysql_query("select id, description from tabel");
$row = mysql_fetch_assoc($q);
$html = $row["description"];
preg_match( '#src="([^"]+)"#', $html, $match );
$src = array_pop($match);
echo $src;
You'll be needing to use SQL Wildcard Characters
So your query can be something like:
select * from tabel where description like '%school%';
EDIT :
I guess you need to get description first then according to it you want to manage the output.
For that try this :
$sqldata= mysqli_query('select * from tabel)';
$rowcount=mysqli_num_rows($sqldata);
if($rowcount > 0)
{
while($result = mysqli_fetch_assoc($sqldata)) // fetch records
{
$description = $result['desription'];
$id = $result['id'];
}
}
I'm trying to place one mysql select inside another one and combine the results to be displayed.
this is my code:
$allattrs = "";
$sql69 = "SELECT * FROM product_details";
$query69 = mysqli_query($db_conx, $sql69);
$login_check69 = mysqli_num_rows($query69);
if($login_check69 > 0){
while($row69 = mysqli_fetch_array($query69, MYSQLI_ASSOC)){
$FID = $row69["id"];
$sql2s = "SELECT * FROM ATTRIBUTES WHERE id='$FID'";
$query2s = mysqli_query($db_conx, $sql2s);
$login_check2s = mysqli_num_rows($query2s);
if($login_check2s > 0){
while($row2s = mysqli_fetch_array($query2s, MYSQLI_ASSOC)){
// Get member ID into a session variable
$Sid = $row2s["id"];
$attr = $row2s["attr"];
$allattrs .= ''.$attr.', ';
}
}
$product_list .= '<tr>
<td>'.$allattrs.'</td>
</tr>';
}
}
The problem i'm having is that the $allattrs returns the values but it will put everthing together.
for example:
if one attr column in mysql database has apples, and another one has oranges, when i see the results of $allattrs on my PHP page i see this:
id 1 - apples
id 2 - apples, oranges
id 3 - apples, oranges, apples, oranges
etc etc
this is in fact wrong as each attribute value needs to stay true to their own id and product_details id field!
I'm not sure what I am doing wrong to cause this.
could someone please advise on this issue?
any help would be appreciated.
The right way to write your query is using JOIN, EXISTS, or IN. I think you would find this most natural:
SELECT a.id, GROUP_CONCAT(a.attr) as attrs
FROM ATTRIBUTES a
WHERE a.id IN (SELECT id FROM product_details)
GROUP BY a.id;
This replaces a bunch of your code.
Looks like you are only interested in the the attributes then try this out instead of the first sql:
SELECT * FROM ATTRIBUTES where id IN (SELECT id FROM product_details)
You need to set $allattrs to an empty string inside your first while loop, instead of only once before.
Apart from that, you should look into the following two topics: Normalization and JOINs.
I want a search query to return results that match all keywords, but I can only get it to either match any or match string.
I.E. "cake chocolate" either returns all records with "cake" OR "chocolate" in a tag field, or results with the exact tag "cake chocolate", as opposed to what I want, which is to get any record with "cake" AND "chocolate". Here is what I've got:
$key = $this->input->post('searchTerm');
if($key != ''){
// if I comment out the next 10 lines, it becomes MATCH-ANY
$this->db->or_like('product_name',$key);
$this->db->or_like('product_code',$key);
$this->db->or_like('description',$key);
$this->db->or_like('season',$key);
$this->db->or_like('year',$key);
$this->db->or_like('photo_style',$key);
$this->db->or_like('photo_status',$key);
$this->db->or_like('extra_field1',$key);
$this->db->or_like('extra_field2',$key);
$this->db->or_like('additional_notes',$key);
// But if I comment out the next 7 lines instead, I match only the entire string.
$Singlequry = "select * from (select *, concat_ws(' ',product_name,product_code,description,season,year,photo_style,photo_status,extra_field1,extra_field2,additional_notes) merged from records )temp where ";
$keywordsMany = explode(' ',$key);
$tempQuery = array();
foreach($keywordsMany as $each){
$tempQuery[] = " temp.merged like '%".mysql_real_escape_string($each)."%'";
}
$Singlequry = $Singlequry.implode(' or ',$tempQuery); // end of search type comment-out
$makeQuery = true;
}
In case it's not obvious, I really have no idea what I'm doing. I've thrown where_in and other stuff in place of the or_like but with no luck. All this to say, I will need a little hand-holding:)
Unfortunately you cannot produce this query with codeigniter or_like;
Your current code produce your query like this
SELECT * from tablename WhHERE product_name like '%key%' or product_code like '%key%' OR..............
which will return only any match with the key.
BUT I guess you want all match which should be like this
SELECT * from tablename WhHERE product_name like '%key%' AND product_code like '%key%' AND..............
if so you can replace your or_like with where like followings
$this->db->where("product_name LIKE '%$key%'");
$this->db->where("product_code LIKE '%$key%'");
$this->db->where("description LIKE '%$key%'");
It will produce your expected query.It will return results which has all match with key.
You can do it many other way too.
Hope it will will help you.
I currently use a mysql statement like the one below to search post titles.
select * from table where title like %search_term%
But problem is, if the title were like: Acme launches 5 pound burger and a user searched for Acme, it'll return a result. But if a user searched for Acme burger or Acme 5 pound, it'll return nothing.
Is there a way to get it to return results when a users searches for more than one word? Is LIKE the correct thing to use here or is there something else that can be used?
You could use a REGEXP to match any of the words in your search string:
select *
from tbl
where
title REGEXP CONCAT('[[:<:]](', REPLACE('Acme burger', ' ', '|'), ')[[:>:]]')
Please notice that this will not be very efficient. See fiddle here.
If you need to match every word in your string, you could use a query like this:
select *
from tbl
where
title REGEXP CONCAT('[[:<:]]', REPLACE('Acme burger', ' ', '[[:>:]].*[[:<:]]'), '[[:>:]]')
Fiddle here. But words have to be in the correct order (es. 'Acme burger' will match, 'burger Acme' won't). There's a REGEXP to match every word in any order, but it is not supported by MySql, unless you install an UDF that supports Perl regexp.
To search for a string against a text collection use MATCH() and AGAINST()
SELECT * FROM table WHERE MATCH(title) AGAINST('+Acme burger*')
or why not RLIKE
SELECT * FROM table WHERE TITLE RLIKE 'Acme|burger'
or LIKE searching an array, to have a compilation of $keys
$keys=array('Acme','burger','pound');
$mysql = array('0');
foreach($keys as $key){
$mysql[] = 'title LIKE %'.$key.'%'
}
SELECT * FROM table WHERE '.implode(" OR ", $mysql)
What you need to do is construct a SQL such that, for example:
select * from table where title like "%Acme%" and title like "%burger%"
In short: split the string and create one like for each part.
It might also work with replacing spaces with %, but I'm not sure about that.
The best thing is thing use perform union operation by splitting your search string based on whitespaces,
FOR Acme 5 pound,
SELECT * FROM TABLE WHERE TITLE LIKE '%ACME 5 POUND%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%ACME%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%5%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%POUND%'
Find out a way to give the first query a priority. Or pass the above one as four separate queries with some priority. I think you are using front end tp pass query to data bases, so it should be easy for you.
<?php
$search_term = 'test1 test2 test3';
$keywords = explode(" ", preg_replace("/\s+/", " ", $search_term));
foreach($keywords as $keyword){
$wherelike[] = "title LIKE '%$keyword%' ";
}
$where = implode(" and ", $wherelike);
$query = "select * from table where $where";
echo $query;
//select * from table where title LIKE '%test1%' and title LIKE '%test2%' and title LIKE '%test3%'
I've looked around for info on an efficient 'related videos' algorithm but i'm struggling to get well ordered, accurate results
I get given the 'genre' as a pipe-delimited string. eg: |Action|Sci-Fi|Thriller|
$genre = explode("|", $row['genre']);
if (count($genre) == 3) {
$sql = "SELECT title FROM `movie` WHERE genre LIKE '%$genre[1]%' LIMIT 0,8";
} else {
$sql = "SELECT title FROM `movie` WHERE (genre LIKE '%$genre[1]%' AND genre LIKE '%$genre[2]%') UNION SELECT title FROM `movie` WHERE (genre LIKE '%$genre[1]%' OR genre LIKE '%$genre[2]%') LIMIT 0,10";
}
$related = mysql_query($sql);
Then I basically explode it and do a manual, inefficient search for genre matches depending on genre count. The results are poor and returns anything that is semi related.
This code makes me want to gag! It works but I hate it and I know its uber lame. Any tips to improve the SQL and getting richer results?
Move the mappings of genres to movies into a new table movie_genres with columns movie and genre.
This allows you to do this:
$genres = explode('|', trim($row['genre'], '|'));
$sql = "SELECT `movie`, COUNT(*) AS hits
FROM `movie_genres`
WHERE `genre` IN ('" . join("', '", $genres) . "')
GROUP BY `movie`
ORDER BY `hits` DESC
LIMIT 8";
You have to make sure to prevent SQL injection, though.
The extra table is also a good idea, because your database schema is not normalized. Especially Chris Date's fourth condition of the first normal form is violated:
Every row-and-column intersection contains exactly one value from the applicable domain (and nothing else).