MySQL UTF-8 Full Text Search with multiple bound parameters - php

My query shows like that:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = :id
AND province = :province
AND MATCH (location) AGAINST (:location);
in practise:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = 3
AND province = 5
AND MATCH (location) AGAINST ('Krakow');
And if I try this query, mysql finally get 0 results.
The problem is polish phrases in query. When I replaced this query for:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = 3
AND province = 5
AND MATCH (location) AGAINST ('Krakow') COLLATE utf8_unicode_ci;`
I got:
Syntax error or access violation: 1253 COLLATION 'utf8_unicode_ci' is not valid for CHARACTER SET 'binary''
I don't know what collate I should use in script php and in mysql. Can you help me?
PS. Sorry for my "best english" bro.

What's the table schema?
I guess 'location' is defined as a binary string and cannot be compared using a collation like utf8_unicode_ci.
Give a read here for more info.
http://dev.mysql.com/doc/refman/5.0/en/charset-binary-collations.html
Edit:
Tell us your schema for further help. However try something like this:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = 3
AND province = 5
AND MATCH (CONVERT(BINARY(location) USING utf8)) AGAINST ('Krakow');

EDITED as per discussion in comments:
As your table scheme looks fine (in terms of utf8) and the first code example you gave in OP is correct (the one without collate), assuming you've got the proper DB collation and the connection itself as well - most probably you have Kraków for advert_location in more than 50% of rows and that is why you get 0 rows of result.
If you want to user Full Text Search, you have to always remember that if a table's fulltext index contains a keyword that appears in 50% of the data rows, that keyword will be ignored by the match query.
So instead you can use Full Text Serach in boolean mode to bypass the 50% threshold. Check the docs here MySQL Boolean Full-Text Searches
So for example, if you have 3 rows in table with Kraków, Krakow and Warszawa as advert_location, the below query will give you 0 rows result:
SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`) AGAINST ('Kraków')
But if you use the boolean mode, you will get 2 rows result:
SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`) AGAINST ('Kraków' IN BOOLEAN MODE)
If you wish to match multiple words, you can use the "+" operator (refer to the docs linked above for details).
SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`,`advert_title`) AGAINST ('+Kraków' '+Search phrase' IN BOOLEAN MODE)
One remark, remember to construct the bound parameter already with the "+" operator included, for example if you are using PHP you can do like this:
$query= "SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`,`advert_title`) AGAINST (:location :title IN BOOLEAN MODE)";
$SQL=$db->prepare($query);
$SQL->bindValue(':location', '+'.$searched_location, PDO::PARAM_STR);
$SQL->bindValue(':title', '+'.$searched_title, PDO::PARAM_STR);

Related

match against shows only exact matches or matches data with some suffix not prefix, in MySQL fulltext search

I have already searched online but not find any use full link Fulltext search only returns exact matches
I have column posttitle with row values
shiva
goodshiva
goodshiva
goodshivagood
Query:
SELECT * FROM `jobs` WHERE match(posttitle) against('shiva' in boolean mode)
and
SELECT * FROM `jobs` WHERE match(posttitle) against('*shiva*' in boolean mode)
doesn't return any value
SELECT * FROM `jobs` WHERE match(posttitle) against('shiva*' in boolean mode)
and
SELECT * FROM `jobs` WHERE match(posttitle) against('+shiva*' in boolean mode)
shows only shivagood and shiva
using natural language mode shows only exact match.
Is there any way without using like?
You have found a limitation to mysql full text search.
There is no equivalent syntax to
LIKE '%something%'
While MySQL itself will return a result for that type of query, no index can be used, so the table involved will be "table scanned"
The full text match syntax of +shiva* will only match when a word starts with shiva. It will not match for words that contain shiva but do not start with shiva.
*shiva*
Is not supported.
Due to this limitation and other issues with full text search, many websites utilize an external search engine like sphinx or solr. Sphinx for example, does allow for
'*shiva*'.

Advanced search in mysql column with row of words separated by coma

Hello everyone as the topic says I am looking for alternative or advanced using of "LIKE".
I have column which contains a row of words p.e. "keyword1,keyword2,another_keyword" and when I use
$sql = mysql_query("SELECT * FROM table WHERE `column` LIKE '%keyword1%' ");
It hardly find it p.e. this example works but when i try to find shorter strings it has problems and sometimes it does not find anything.
I tried put a whitespace after comas and it helped but if there is a way where I can search for match with this specification of column I would be happy.
You may move keywords into individual table.
Or you can use SET field type, if the list of your keywords don't change.
Storing comma separated list of your words is a bad idea example using like in your scenario is hard to find the exact work in comma separated list instead you can add new table which relates to your current table and store each the word in a new row with the associated identity like
table1
id title
1 test1
2 test2
kewords_table
table1_id word
1 word1
1 word2
1 word3
and query will be
select t.*
from table1 t
join kewords_table k
on(t.id = k.table1_id)
where k.word = 'your_keyword'
If you can't alter your structure you can use find_in_set()
SELECT * FROM table WHERE find_in_set('your_keyword',`column`) > 0
try something like this:
SELECT * FROM tablename
WHERE column LIKE '%keyword1%'
OR column LIKE '%keyword2%';
for more info see here:Using SQL LIKE and IN together
MySQL allows you to perform a full-text search based on very complex queries in the Boolean mode along with Boolean operators. This is why the full-text search in Boolean mode is suitable for experienced users.
First You have to add FULLTEXT index to that perticuler column :
ALTER TABLE table_name ADD search_column TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, ADD FULLTEXT search_column (search_column);
Run following query for searching :
SELECT * FROM table WHERE MATCH(search_column) AGAINST("keyword1")
for more info see here : https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html

how to count the number of rows in SQL table using specific criteria?

I have two columns of data. One column is called "like" which holds either the number 1 or 0. The other column is called "object" which can hold any word. I want to count the number of rows where the number 1 in the "like" column coincides with a certain word in the "object" column.
I have tried
$numrow1 = mysql_query("SELECT * FROM tablename WHERE like = 1 AND object = '$object' ");
$numlikes = mysql_num_rows($numrow1);
but I got a syntax error. Any help would be appreciated.
LIKE is a sql string comparison operator, maybe even object. If you have a field with a reserved name, then you have to directly address it or escape it.
Reformat your SQL statement inside the mysql_query like this:
SELECT *
FROM tablename AS T
WHERE T.like = 1
AND T.object = '$object'
If you only want to get the number of rows using, count() is much more efficient:
SELECT count(*)
FROM tablename
WHERE `like` = 1
AND object = '$object'
You did not show us the error message, but I gues it's because like is a reserved word, and therefor you need to quote the column name (I would strongly recommend to use a different name to avoid those problems in the future).
If you are running MySQL in ANSI compliant mode, you can also use the standard double quotes to escape the column name:
SELECT count(*)
FROM tablename
WHERE "like" = 1
AND object = '$object'
I'm not sure, but object could be a reserved word as well, so that might need quoting too.

Search keyword with mysql

What should I use, to search for a keyword with mysql ?
I have a word and in the query I have
wordless
something word something
someword some
else
other
wordother
thingword
I want to output everything that has the word inside it, but the output to be like first outputed rows to be that rows with word as first letter on them, for example
wordless - will be the first because word are first characters of the word wordless
and the wordother to be outputed to to the first outputed rows, then after them to output something word something and etc, every word that contains the name word, but again to output first that rows that have the word at the first characters.
EDIT:
SELECT *,MATCH(add_songName) AGAINST('d' IN BOOLEAN MODE) asscoreFROM songs WHERE MATCH(add_songName) AGAINST('d') ORDER BYscoreDESC , Here i'm searching for d but it gives me an error -
Can't find FULLTEXT index matching the column list SELECT *,MATCH(add_songName) AGAINST('d' IN BOOLEAN MODE) as `score` FROM songs WHERE MATCH(add_songName) AGAINST('d') ORDER BY `score` DESC
Try to use Levenshtein algorithm in MySQL.
Levenshtein matching is a metric for measuring the amount of difference between two sequence, here it is strings. By default MySQL does not have this function, but you can write and add one.
Please take a look at the code here and add that code as a system function in MySQL, please see the example below on how to get the similarity of two strings.
Please see: https://github.com/rakesh-sankar/Tools/blob/master/MySQL/Levenshtein.txt
Example:
SELECT column1, LEVENSHTEIN(column1, 'matchme') AS perfectmatch FROM sometable ORDER BY perfectmatch DESC

mysql multi-table fulltext query problem?

I am making a multi-table fulltext query.But I met some question.
I need make a query like
(SELECT
title,content,date,cat
FROM article1
WHERE
cat='Science fiction'
AND
MATCH (title,content)
AGAINST
('+Harry +Potter' IN BOOLEAN MODE))
UNION
(SELECT
title,content,date
FROM article3
WHERE MATCH (title,content)
AGAINST
('+Harry +Potter' IN BOOLEAN MODE))
Order By date DESC LIMIT 10
But it caused Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource
If I deleted cat='Science fiction' AND it can pass the test.
Where is the problem? If I want make a query what I want: first fulltext query require need meet cat='Science fiction'. Thanks a lot.
You are trying to UNION together result sets that return a different number of columns. Your first query returns 4 columns (title,content,date,cat) while your second only returns 3 (title,content,date). Each query must return the same number of columns.
I don't know why removing the cat LIKE 'Science fiction' makes the query work. As written, it should not work in either case. UNION requires both parts of the queries to produce the same number of columns with compatible types. Your UNION has 4 columns in the first part and 3 columns in the second:
SELECT title, content, date, cat FROM article1
UNION
SELECT title, content, date FROM article3
Did mysql_query return FALSE, indicating a problem parsing your query? If you blindly passed "FALSE" into mysql_fetch_array(), I'd expect to see that kind of error.
try
cat LIKE 'Science fiction'

Categories