mysql: order by match - php

for looking up matching keywords in mysql i use
SELECT * FROM `test` WHERE `keywords` REGEXP '.*(word1|word2|word3).*' LIMIT 1
I want to order them by the most matching keywords in the keywords column to give the best answer.For example
Keywords /////////////// Response
word1,word2 /////////// test1
word1,word2,word3 / test2
I want the response to be test2 with the query given.
How can i order the results my the most matching keywords?

SELECT
(keywords REGEXP '.*(word1).*')
+(keywords REGEXP '.*(word2).*')
+(keywords REGEXP '.*(word3).*') as number_of_matches
,keywords
,field1
,field2
FROM test
WHERE keywords REGEXP '.*(word1|word2|word3).*'
ORDER BY number_of_matches DESC
LIMIT 20 OFFSET 0

Related

MySQL Similar 2 Columns need begining data by 1st column

$genre = 'Action|Adventure|Crime';
$starcast= 'Tom Hanks|Felicity Jones|Omar Sy|Irrfan Khan';
$S2 = mysql_query("SELECT title,hash,year FROM IMDB WHERE starcast REGEXP '".$starcast."' or genre REGEXP '".$genre."' LIMIT 16") or die (mysql_error());
while ($S = mysql_fetch_assoc($S2)){
this is working but results are in mixed data.
data LIMIT is 16.
i want 1st all data by starcast.
Example :- If startcast data match with 9 result so last 7 data needed match with genre.
sorry for bad English.
Question is UPDATE.....
I doubt how your posted query works. It should throw compilation error. Your query should look like
SELECT title,hash,year
FROM IMDB WHERE starcast REGEXP '".$starcast."' or genre REGEXP '".$genre."'
ORDER BY id DESC
LIMIT 16
If startcast data match with 9 result so last 7 data needed match with genre
don't think you can make it like that unless you use UNION query like
(SELECT title,hash,year
FROM IMDB WHERE starcast REGEXP '".$starcast."'
ORDER BY id DESC LIMIT 9)
UNION
(SELECT title,hash,year
FROM IMDB WHERE genre REGEXP '".$genre."'
ORDER BY id DESC LIMIT 7 )

MySQL sort by number of occurrences

I am doing a search in two text fields called Subject and Text for a specific keyword. To do this I use the LIKE statement. I have encountered a problem when trying to sort the results by the number of occurrences.
my search query looks like this:
SELECT * FROM Table WHERE (Text LIKE '%Keyword%' OR Subject LIKE '%Keyword%')
I tried to add a count() statement and sort it by the number of occurrences, but the count() statement just keep returning the number of rows in my table.
Here is the query with count statement:
SELECT *, COUNT(Text LIKE '%Keyword%') AS cnt FROM News WHERE (Text LIKE '%Keyword%' OR Subject LIKE '%Keyword%') ORDER BY cnt
What im looking for is something that returns the number of matches on the Subject and Text columns on each row, and then order the result after the highest amount of occurrences of the keyword on each row.
Below query can give you the no.of occurrences of string appears in both columns i.e text and subject and will sort results by the criteria but this will not be a good solution performance wise its better to sort the results in your application code level
SELECT *,
(LENGTH(`Text`) - LENGTH(REPLACE(`Text`, 'Keyword', ''))) / LENGTH('Keyword')
+
(LENGTH(`Subject`) - LENGTH(REPLACE(`Subject`, 'Keyword', ''))) / LENGTH('Keyword') `occurences`
FROM
`Table`
WHERE (Text LIKE '%Keyword%' OR Subject LIKE '%Keyword%')
ORDER BY `occurences` DESC
Fiddle Demo
Suggested by #lserni a more cleaner way of calculation of occurrences
SELECT *,
(LENGTH(`Text`) - LENGTH(REPLACE(`Text`, 'test', ''))) / LENGTH('test') `appears_in_text`,
(LENGTH(`Subject`) - LENGTH(REPLACE(`Subject`, 'test', ''))) / LENGTH('test') `appears_in_subject`,
(LENGTH(CONCAT(`Text`,' ',`Subject`)) - LENGTH(REPLACE(CONCAT(`Text`,' ',`Subject`), 'test', ''))) / LENGTH('test') `occurences`
FROM
`Table1`
WHERE (TEXT LIKE '%test%' OR SUBJECT LIKE '%test%')
ORDER BY `occurences` DESC
Fiddle Demo 2
You want SUM instead. Count will count how many records have non-null values, which means ALL matches and NON-matches will be counted.
SELECT *, SUM(Text LIKE '%Keyword') AS total_matches
...
ORDER BY total_matches
SUM() will count up how many boolean true results the LIKE produces, which will be typecast to integers, so you get a result like 1+1+1+0+1 = 4, instead of the 5 non-nulls count.
// escape $keyword for mysql
$keyword = strtolower('Keyword');
// now build the query
$query = <<<SQL
SELECT *,
((LENGTH(`Subject`) - LENGTH(REPLACE(LOWER(`Subject`), '{$keyword}', ''))) / LENGTH('{$keyword}')) AS `CountInSubject`,
((LENGTH(`Text`) - LENGTH(REPLACE(LOWER(`Text`), '{$keyword}', ''))) / LENGTH('{$keyword}')) AS `CountInText`
FROM `News`
WHERE (`Text` LIKE '%{$keyword}%' OR `Subject` LIKE '%{$keyword}%')
ORDER BY (`CountInSubject` + `CountInText`) DESC;
SQL;
Returns number of occurrences in each field and sorts by that.
The 'keyword' needs to be lower cased for this to work. I don't think it's really fast, performance wise as it needs to lower-case fields and there's no case-insensitive search in MySQL afaik.
You could index each news item (subject and text) by words and store in another table with news_id and occurrence count and then match against that.

Can't get around "Unknown Column In Field List" in SQL

I have a search script which searches in table1.title to match titles to search queries and orders them based on score but I also want it to search and compare in table2.title. When I try to add table2.title to the script I get a Unknown Column error. It seems as if the script is rooted in table1 and can't get information from other tables.
Here is the code of the search script:
"SELECT * , CASE WHEN table1.title OR table2.title LIKE
'%".mysql_real_escape_string(like($_GET['search']), $db)."%'
THEN 1 ELSE 0 END as score , MATCH table1.title AGAINST
('".mysql_real_escape_string($_GET['search'], $db)."')
AS score2 FROM table1 WHERE 1=1 AND MATCH (table1.title) AGAINST
('".mysql_real_escape_string($_GET['search'], $db)."') ".
"ORDER BY table1.priority DESC , score DESC, score2 DESC ".
"LIMIT ".(($page - 1) * $pp).", {$pp} ",
$db
Any help would be greatly appreciated! Thanks!

MySql query challenge - return results with whitespace?

I have a MySql database with some rows as follows:
ID DESC
1 This is my bike
2 Motorbikes are great
3 All bikers should wear helmets
4 A bike is great for exercise
5 A. Top. Bike.
What I want to do is return the rows with whitespace surrounding the search term, OR the term being at the end or beginning of the description.
For example,
"SELECT * FROM `mytable` WHERE `desc` LIKE '%bike%'"
Will return all rows. But,
"SELECT * FROM `mytable` WHERE `desc` LIKE '% bike %'
Will only return row 4.
What I really want is a reliable way to return rows 1, 4 and 5, i.e. where the search term is sorrounded with anything BUT chars A-z, 0-9. Any ideas? Is this even possible with MySql?
Thanks!!
You can use regular expressions in SQL
SELECT * FROM `table` WHERE desc REGEXP '\bbike\b'
You should start reading about MySql RegEx.
Sample Code.
SELECT * FROM table WHERE field_name REGEXP PATTERN;
More Specific
details Table
ID NAME
1 Dipesh
2 Dip
3 Dipe
4 DiDi
5 Di
SELECT * FROM details WHERE NAME REGEXP '^Di$';
Result
NAME -> Di
SELECT * FROM details WHERE NAME REGEXP 'Di$';
Result
NAME -> DiDi , Di
SELECT * FROM details WHERE NAME REGEXP '^Di';
Result
NAME -> Dip, DiDi, Di
You need to specify the additional conditions in the query:
SELECT *
FROM `mytable`
WHERE
`desc` LIKE '% bike %' OR
`desc` LIKE '% bike' OR
`desc` LIKE 'bike %';
Try this one, hope it'll help you
"SELECT * FROM `mytable` WHERE `desc` LIKE '% bike'

php and regex: search for word in string

How can i found word in string using regex or not in this string
String is Mysql Query
SELECT
id,
name,
desc,
(SELECT id as lid FROM comments WHERE lid = id order by id desc limit 1) as lid_com
FROM posts limit 3
here i want to search for limit in the last of string
string may be
limit 3
limit 3, 3
limit 3 , 3
limit 3 ,3
3 here may be any number
i tried this regex but i'm beginner
"/ limit [0-9]{0,9}+\,[0-9]{0,9} /i$"
how can i do this
Thank you
$string = 'SELECT
id,
name,
desc,
(SELECT id as lid FROM comments WHERE lid = id order by id desc limit 1) as lid_com
FROM posts limit 3 ,3';
echo preg_match('/(limit)\s\d(((\,\s)|(\s\,\s)|(\s\,))\d)?$/i', $string, $matches); //1
print_r($matches); //$matches['0'] == 'limit 3 ,3'
"/limit[\s]+[\d]+[\s]*,[\s]*[\d]+$/i"
This searches case insesitive for:
"limit"
one or more whitespaces
one or more digits
zero or more whitespaces
a comma
zero or more whitespaces
one or more digits
at the end of the string
Do not remember, whether LIMIT is always a last SQL statement, so I'd use
/limit\s+(\d+)(?:\s*,\s*(\d+))?(?=[^\n]+\Z)/mi
Try this condition -
SELECT * FROM table WHERE column
REGEXP '(^limit[[:space:]]+[[:digit:]]+[[:space:]]*,[[:space:]]*[[:digit:]]+$)|(^limit[[:space:]]+[[:digit:]]+[[:space:]]*$)';
The first part find strings like 'limit 3,3' -
^limit[[:space:]]+[[:digit:]]+[[:space:]]*,[[:space:]]*[[:digit:]]+$
The second one finds strings like 'limit 3' -
^limit[[:space:]]+[[:digit:]]+[[:space:]]*$

Categories