I used wildcards for the query
$query = mysql_query("SELECT id FROM products WHERE name LIKE '%$term%'");
and it gives me the results.
but when I use
$query = mysql_query("SELECT id FROM products WHERE MATCH (name) AGAINST ('$term')");
it does not show me any.
Why is that ?
As there is only one product, you might run into the 50% threshold:
In addition, words that are present in 50% or more of the rows are
considered common and do not match. Full-text searches are natural
language searches if no modifier is given.
Full Text Search
Related
How to create sql select by 3 level expression and statement
Normally, my website based on SQLite database and the search result will be display by $sql =
"SELECT DISTINCT * FROM amz WHERE Title LIKE \"$qq%\" OR Price LIKE \"$qq%\" GROUP BY Title";.
Above will be search and select query that contains any search keyword from database in column Title or Price.
However, I need to create 3 expression and statement from database as:
Default will be search and display result as $sql = "SELECT DISTINCT * FROM amz WHERE Title LIKE \"$qq%\" OR Price LIKE \"$qq%\" GROUP BY Title";
If can't find any search result from Title and Price column. Then SQL will be check in Category column as $sql = "SELECT DISTINCT * FROM amz WHERE Category LIKE \"$qq%\" GROUP BY Title";
Finally, if not match in each column. SQL result will be echo custom message.
I try to create with myself. But it seems the result echo 1.) option only.
Example:
I search “bedding comforter set”. And in column Title in database had products contain this keyword without (s).
Initially, an expression will be check if it match 1). A statement will do selecting products from column Title or Price.
However, in column Category. I declare specific category to each product such as “bedding comforter sets” to Category.
So, if search not match bedding comforter sets in Title or Price. The result will be display products that match search query of bedding comforter sets in column Category instead Title or Price.
Finally, if not search query not match any in each column will be echo custom message.
Additional:
This is a screebshot comparing between query 1 and query 2 result
This screenshot is query 1 result that search keyword without (s) and like or match in Title column or Price column from database.
This screenshot is query 2 result that search keyword with (s) which like or match in Category column. This strange because it turns as Not Found while I set it to display result.
And this is my coding that I not sure it correct or not?
Thanks
Regards
Is there a requirement to write one sql to accomplish this?
You have essentially written pseudo-code:
Default will be search and display result as $sql = "SELECT DISTINCT * FROM amz WHERE Title LIKE \"$qq%\" OR Price LIKE \"$qq%\"
GROUP BY Title";
If can't find any search result from Title and Price column. Then SQL will be check in Category column as $sql = "SELECT DISTINCT * FROM
amz WHERE Category LIKE \"$qq%\" GROUP BY Title";
Finally, if not match in each column. SQL result will be echo custom message.
Now start expressing it in language the machine understands. A starting point:
execute and fetch result from query 1
if result set is not empty, display result
else execute and fetch result from query 2
if result set is not empty, display result
else display custom message
--EDIT --
Based on screenshot of code, you are not running the mentioned queries at all, but some other query modified by the str_repl. Which seems to morph it into an aggregate query (COUNT(*)), and aggregate queries always return at least one row. That could cause this problem.
I'm trying to modify an existing script I have, that will only output rows that contain specific area codes to users that have be assigned the specific area codes.
Example:
A column named designed_areas in the users table will contain different data like: CM,SS,RH
When a lead comes in, I'm using substr to detect the first 2 characters of a post code.
$trimmed = substr("$postcode", 0, 2);
$viewLeads=mysqli_query($con,"SELECT * FROM leads WHERE team = '$getID->team' ORDER BY id DESC");
while($lead=mysqli_fetch_object($viewLeads)){
I'd like to expand on the mysqli_query and select all the leads from the database where the first 2 characters of the postcode matches any of users designated_areas.. which are comma seperated.
This way, he'll only see leads with the areas he can work on.
Can anyone help?
You can try to use a query like:
SELECT * FROM leads WHERE team = '$getID->team' and designed like '%{$trimmed}%' ORDER BY id DESC;
Php code:
$viewLeads=mysqli_query($con,"SELECT * FROM leads WHERE team = '$getID->team' and designed like '%{$trimmed}%' ORDER BY id DESC;");
You can do it with a regex. For example, in MySQL, if your postal_code table looks something like this:
PersonID Zips
1 11111,22222,33333
2 22222,12121,32323
And you want persons that have postal codes like 33*
SELECT PersonID FROM `postal_code` WHERE zips rlike '33[0-9]{3}'
This assumes that all postal codes are 5 digits and you're always searching using 2 digits. It basically says "find me 5 digit numbers where the first two digits are 33" or whatever your search numbers are.
The PHP code might look like:
$search = 33 ;
$sql = "SELECT PersonID FROM `postal_code` WHERE zips rlike '$search[0-9]{3}'" ;
This solution will find matches regardless of commas, spaces, etc. You won't need any further processing in your PHP code.
So I'm working on a search function for a social networking site, and it searches user posts. Some users like to put hyphens instead of spaces, but I would like for the search function look for both hyphens and spaces in a result.
For example, if they have a post named "SQL-IS AWESOME" and I search for "SQL IS AWESOME", can I still find that post? I tried using 2 sql queries, one for the original search query, and one modified to change all spaces to hyphens.
But if I search "SQL IS-AWESOME" it still won't find it. Is there an easier way?
My current code:
$sql = "SELECT * FROM posts
WHERE (post_title='".$query."'
OR post_title LIKE '%".$query."'
OR post_title LIKE '%".$query."%'
OR post_title LIKE '".$query."%')
".$locquery."
".$cat."
ORDER BY date DESC
LIMIT 18";
As someone has suggested, you could just adapt and use fulltext searching.
If you choose to take this route, you will need to enable fulltext searching on the fields required.
I'll assume you will check post_title and post_body (?), which needs you to run this;
ALTER TABLE `posts` ADD FULLTEXT KEY `post_search` (`post_title`,`post_body`);
When that is done, your search query can easily be edited to become;
$sql = "SELECT * FROM `posts` WHERE MATCH(post_title,post_body) AGAINST '$search'";
If you'd like better matching, it is also possible to give it a score and order by that, which would require code similar to this:
$sql = "SELECT *, MATCH(post_title, post_body) AGAINST ('{$search}') AS score ".
"FROM `posts` WHERE MATCH(post_title, post_body) AGAINST ('{$search}') ORDER BY `score` DESC";
--- NOTES
For the search, you need to work out how you will be searching.
In the last instance I used similar, I simply had a form for the search term (Named "Search") resulting in $_POST['search'] being sent to the server.
I then used;
$search = (array_key_exists('search', $_POST) && is_string($_POST['search'])) ? mysql_real_escape_string($_POST['search'], $c) : FALSE ;
if ($search) {
// Do the fulltext query requires (See above)
}
Since fulltext search will disregard the hyphen, you are left with just spaces, which works great for fulltext, if you opt to use scored results.
I want to make a search tool for my website.
if i search for a phrase i want it to search multiple columns
for example if i search dewalt drill and the title has the works dewalt power drill i want it to come up.
also if i search dewalt drill and the tile has dewalt and the description has drill i want it to come up.
but all words of the search must be contained in any combination of fields.
can someone help me with the query?
Currently:
{Select * from products where sku like '%{$searchwords}%' or title like '%{$searchwords}%' or desc like '%{$searchwords}%}
If your table is myisam you can create a fulltext index then use in boolean mode
to add the key:
alter table products ADD FULLTEXT (sku, title, desc)
then your query would be:
$searchwords = join(' +', explode(' ', $searchwords));
$query = "SELECT * FROM products WHERE MATCH (sku, title, desc) AGAINST ('{$searchwords}' IN BOOLEAN MODE)";
Your probably want FULLTEXT searching (starting with MySQL 5.6, this is also available for InnoDB tables). You can require all words with BOOLEAN MODE.
I don't know why I can't find this anywhere. I would think this would be pretty common request. I am writing a search engine in PHP to search a MySQL database of For Sale listings for keywords inputted by the user.
There are several columns in the table but only 2 that will need to be searched. They are named file_Title & file_Desc. Think of it like a classified ad. An item title and a description.
So for example a user would search for 'John Deere Lawn Tractor'. What I would like to happen is classifieds that have all 4 of those words show up at the top of the list. Then results that only have 3 an so on.
I've read a very good webpage at http://www.roscripts.com/PHP_search_engine-119.html
From that authors example I have the following code below:
<?php
$search = 'John Deere Lawn Tractors';
$keywords = split(' ', $search);
$sql = "SELECT DISTINCT COUNT(*) As relevance, id, file_Title, file_Desc FROM Listings WHERE (";
foreach ($keywords as $keyword) {
echo 'Keyword is ' . $keyword . '<br />';
$sql .= "(file_Title LIKE '%$keyword%' OR file_Desc LIKE '%$keyword%') OR ";
}
$sql=substr($sql,0,(strLen($sql)-3));//this will eat the last OR
$sql .= ") GROUP BY id ORDER BY relevance DESC";
echo 'SQL is ' . $sql;
$query = mysql_query($sql) or die(mysql_error());
$Count = mysql_num_rows($query);
if($Count != 0) {
echo '<br />' . $Count . ' RESULTS FOUND';
while ($row_sql = mysql_fetch_assoc($query)) {//echo out the results
echo '<h3>'.$row_sql['file_Title'].'</h3><br /><p>'.$row_sql['file_Desc'].'</p>';
}
} else {
echo "No results to display";
}
?>
The SQL String outputted is this:
SELECT DISTINCT COUNT(*) As relevance, id, file_Title, file_Desc FROM Listings
WHERE ((file_Title LIKE '%John%'
OR file_Desc LIKE '%John%')
OR (file_Title LIKE '%Deere%'
OR file_Desc LIKE '%Deere%')
OR (file_Title LIKE '%Lawn%'
OR file_Desc LIKE '%Lawn%')
OR (file_Title LIKE '%Tractors%'
OR file_Desc LIKE '%Tractors%') )
GROUP BY id
ORDER BY relevance DESC
With this code I get 275 results from my DB. My problem is it really doesn't order by the number of keywords found in the row. It seems to order the results by id instead. If I remove 'GROUP BY id' then it only returns 1 result instead of all of them, which is really messing with me!
I've also tried shifting to FULLTEXT in the db but can't seem to get that going either so I'd prefer to stick with LIKE %Keyword% syntax.
Any help is appreciated! Thanks!
I would suggest a totally different approach. Your approach is cumbersome, inefficient, heavy on the DB and will likely be very slow with more and more records added to your database.
What I would suggest is the following:
Create a separate table for keywords.
Create a list of non keywords you don't want to index (like the common English prepositions etc.) so that they are not included. You
can probably find a list of them online, readily available.
When a new entry is added, you split the string into separate keywords, omitting the ones in step 2., and inserting them in the
table created in step 3 (if not already in it).
In a separate table, with a foreign key pointing to the keywords table, associate the classifed_ad to the keyword.
Steps 3 and 4 must happen again if your classified_ad is edited (i.e. any keywords inserted in step 4 deleted from the association table and the keywords analysed again and reassociated with the classified ad).
Once you have this structure, all you have to do is search the association table and order by the number of matched keywords. You can even add an extra column to it and put the number of occurrences of that keyword in the article, so that you order by that too.
That will be much faster.
I had used a script once called Sphider which does something similar. Not sure if it is still maintained, but it works in a very similar way on web pages it parses.
I know you said you had problems with FULLTEXT, but I would highly encourage you to go back and try that again. FULLTEXT indexes and search is designed to do what you are doing, and when the MATCH command is used in the WHERE clause, MySQL automatically sorts the rows from highest to lowest relevance.
For more information on FULLTEXT, check out http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
Also, pay special note to the comment by Patrick O'Lone on the same page, some of which is quoted below...
It should be noted in the documentation that IN
BOOLEAN MODE will almost always return a
relevance of 1.0. In order to get a relevance that is
meaningful, you'll need to:
SELECT MATCH('Content') AGAINST ('keyword1
keyword2') as Relevance FROM table WHERE MATCH
('Content') AGAINST('+keyword1 +keyword2' IN
BOOLEAN MODE) HAVING Relevance > 0.2 ORDER
BY Relevance DESC
Notice that you are doing a regular relevance query
to obtain relevance factors combined with a WHERE
clause that uses BOOLEAN MODE. The BOOLEAN
MODE gives you the subset that fulfills the
requirements of the BOOLEAN search, the relevance
query fulfills the relevance factor, and the HAVING
clause (in this case) ensures that the document is
relevant to the search (i.e. documents that score
less than 0.2 are considered irrelevant). This also
allows you to order by relevance.