Mysql full text returnig NULL - mysql

My mysql code.
CREATE TABLE `videos` (
`id` int(50) NOT NULL,
`user_id` int(250) NOT NULL,
`title` varchar(250) NOT NULL,
`discription` text NOT NULL,
`video_path` varchar(250) NOT NULL,
`tumbnail_path` varchar(250) NOT NULL,
`paid` int(250) NOT NULL,
`date` date NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `videos` (`id`, `user_id`, `title`, `discription`, `video_path`, `tumbnail_path`, `paid`, `date`) VALUES
(1, 4, 'This is a new video', '<p>This is a new video from eduladder in at this video we are discribing how stuffs works</p>\r\n', 'uploadvid/xIdivzexFZXzr6bng2E9mU3PNvMVq0Iz.mp4', 'uploadthump/1AT1EsgJ--6iVLxEwEFRkWa9ADqqD1BG.jpg', 0, '2018-12-10'),
(2, 4, 'New Video for testig', '<p>This is a new video for testing purpose only</p>\r\n', 'uploadvid/_rsIHMc2giVoWV6aRixCoEUk0gKcDhDI.mp4', 'uploadthump/zA_t-2DMusUDvg9xVPwmRAn5-59He76-.jpg', 0, '2018-12-12'),
(3, 4, 'Some New Videos', '<p>This is a record of some new videos</p>\r\n', 'uploadvid/jPzlU3xSJaZVm7EzZu_JfaXq8kAK_1Vc.mp4', 'uploadthump/M_SZodSk20ba2FsXw3X1WVq7a48S_cj3.jpg', 0, '2018-12-13'),
(4, 4, 'Old video', '<p>This is an old video</p>\r\n', 'uploadvid/yaYiDBru2c7fCcosPmrj94JhZ5waxbu8.mp4', 'uploadthump/FhRXXen99DEa0d-8w5m2FDcvFyxlZgx4.png', 0, '2018-12-13'),
(5, 4, 'Almost new video and edited', '<p>This is about almost new video and editted version</p>\r\n', 'uploadvid/YOVPqiFO5xUnCtFAdYzgiY2wzsCnSQ11.mp4', 'uploadthump/MO1faxOKDNESee0gG5SQZYeantzlrPYM.png', 0, '2018-12-13');
ALTER TABLE `videos` ADD FULLTEXT(`title`,`discription`);
And the query which I am excecuting is here.
SELECT * ,
MATCH (title, discription) AGAINST ('New') AS score
FROM videos
WHERE MATCH (title, discription) AGAINST ('New')
ORDER BY score
DESC LIMIT 20
Here's a mysql fiddle https://www.db-fiddle.com/f/jUs9EABZjuBL956WtnTbqx/3
But it is giving me nothing where am I going wrong how can I fix this issue?

Since you asked for it to work with MySql 5.5 in your comment:
Plz see the udated code db-fiddle.com/f/jUs9EABZjuBL956WtnTbqx/3
innodb wont work it is myql version <5.6
Then it's 2 different case. For MySql 5.7, Stopword list applies only.
But for MySql 5.5 from your latest fiddle here are the 2 reasons :
The 1st reason this is not working is because the word you are searching for is present in 50% or more of the total rows, so it is considered as Common Word and won't match as a result. See the Mysql 5.5 FullText Search Docs :
There are three types of full-text searches:
A natural language search interprets the search string as a phrase in
natural human language (a phrase in free text). There are no special
operators, with the exception of double quote (") characters. The
stopword list applies. In addition, words that are present in 50% or
more of the rows are considered common and do not match.
And the 2nd one is because by default the FullText Search Length is set to 4. So you need to change it in my.cnf and add value :
[mysqld]
ft_min_word_len = 3
to be able to search 3 characters words.
But since in db-fiddle I cannot modified the length, here is a modified working fiddle where the word Older is used. Older is not present on 50% of rows and its length is >= 4.

Seems to be an issue with Full text Stop-words on the myisam engine, I changed the engine to InnoDB and I can get results.
See this link. Full-Text Stopwords
To fully disable stopwords, add this ft_stopword_file = '', to your database configuration file, the repair the table to rebuild indexes,
REPAIR TABLE tbl_name QUICK. and restart the server

Related

MySQL full text search - no partial recognition

I'm trying to build a keyword search tool based on mysql and I can only get results for full words while I would like to get results for partial matches too.
My db structure looks like this:
My db content looks like this:
This query works:
select * from chromext_keyword where matches (keyword) against ('Redmi')
But this one doesn't work (no result):
select * from chromext_keyword where matches (keyword) against ('red')
I tried with % but it did not solve the problem. I tried the natural language option as well as boolean but it didn't help.
Update with create table query:
CREATE TABLE chromext_keywords (
id int(10) NOT NULL,
keyword text NOT NULL,
blacklist text NOT NULL,
category text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
and insert:
INSERT INTO chromext_keywords (id, keyword, blacklist, category) VALUES
(1, 'Redmi Note 10', '9,8,pro', '2'),
(2, 'Realme GT', '6,7,8,narzo', '2');
and I added full text:
ALTER TABLE chromext_keywords
ADD UNIQUE KEY id (id);
ALTER TABLE chromext_keywords ADD FULLTEXT KEY keyword (keyword);
I have also tried innoDb and Myisam
Am I missing something?
Thanks
You should check for Minimum word lenght setting ..
in mysql the minimum length for full text search in limited by the param
ft_min_word_len
and the defualt value is for words > 3
take a look at the related docs
https://dev.mysql.com/doc/refman/8.0/en/fulltext-fine-tuning.html
I have finally found the answer.
The following query works:
SELECT * FROM chromext_keywords WHERE match(keyword) against('(re*)') IN BOOLEAN MODE)
With multiple keywords:
SELECT * FROM chromext_keywords WHERE match (keyword) against ('(+red*+not*)') IN BOOLEAN MODE)
I still need to figure out how to cover spelling mistakes. If anyone has an idea, let me know.

What is wrong with MySql LIKE operator on utf8_turkish_ci collation?

I've a table like below:
wordId | word
---------------------------------
1 | axxe
2 | test word
3 | another test word
I'm trying to run the query below to find the records beginning with the letters "ax".
SELECT * FROM `words` WHERE word LIKE 'ax%'
MySQL cannot find anything.
But, if I try one of the queries below I can see the correct record (the word "axxe") on the results.
SELECT * FROM `words` WHERE word='axxe'
SELECT * FROM `words` WHERE word LIKE '%ax%'
SELECT * FROM `words` WHERE word LIKE 'a%'
Why can't MySQL find the correct value for the first query? I've tried to run this both on the command line and phpMyAdmin but the result is the same.
This is SHOW CREATE TABLE output:
CREATE TABLE `words` (
`wordId` int(11) NOT NULL auto_increment,
`word` text collate utf8_turkish_ci NOT NULL
PRIMARY KEY (`word`)
) ENGINE=MyISAM AUTO_INCREMENT=2853 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci
TL;DR:
Update your MySQL version.
I created a simulation of your problem here:
Create table:
CREATE TABLE `turky` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`word` text COLLATE utf8_turkish_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci
Insert data:
INSERT INTO `turky` (`id`, `word`) VALUES
(1, 'axxe'),
(2, 'test word'),
(3, 'axxxxxe'),
(4, 'another test word');
Run test query (that works):
SELECT * FROM `turky` WHERE `word`='axxe'
Result:
1, 'axxe',
Run test query 2 (that works):
SELECT * FROM `turky` WHERE word LIKE '%ax%'
Result:
1, 'axxe',
3, 'axxxxxe',
Run test query 3 (that works):
SELECT * FROM `turky` WHERE word LIKE 'a%'
Result:
1, 'axxe',
3, 'axxxxxe',
4, 'another test word';
Run test query 4 (that does not work originally):
SELECT * FROM `turky` WHERE `word` LIKE 'ax%'
Result:
1, 'axxe',
3, 'axxxxxe',
This works in MySQL, using PHPMyAdmin.
Versions:
MySQL: 5.6.35
PHPMyAdmin: 4.6.6
The current Turkish alphabet doesn't contain the letter "x" so this fact may [probably not] be causing some obscure interference with the SQL sorting process (as in a lack of language guidance when looking for this character).
Web searching Turkish language bugs in MySQL and while there are half a dozen none of them appear to be for your specific instance.
But the only option here that I can see from my own testing (above), using the table and SQL details you've given us, is that you have an older version of MySQL that includes some turkish language bugs.
If your MySQL version is up to date
(or at least, more recent than mine)
Then the issue seems to be specific to your setup and your data, so I highly doubt we can find and reproduce this issue :-(
More Diagnostic stuff:
As commented by Jacob H, see if this issue still occurs after casting to binary:
SELECT * FROM `turky` WHERE BINARY `word` LIKE CONCAT(BINARY 'ax','%');
Result:
1, 'axxe',
3, 'axxxxxe',

MYSQL CSV column check for exclude

I need to find a record who dont have a specific value in CSV column. below is the table structure
CREATE TABLE `employee` (
`id` int NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL,
`keywords` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Sample record1: 100, Sam, Thompson, "50,51,52,53"
Sample record2: 100, Wan, Thompson, "50,52,53"
Sample record3: 100, Kan, Thompson, "53,52,50"
50 = sports
51 = cricket
52 = soccer
53 = baseball
i need to find the employees name who has the tags of "sports,soccer,baseball" excluding cricket
so the result should return only 2nd and 3rd record in this example as they dont have 51(cricket) but all other 3 though in diff pattern.
My query is below, but i couldnt get it worked any more.
SELECT t.first_name,FROM `User` `t` WHERE (keywords like '50,52,53') LIMIT 10
is there anything like unlike option? i am confused how to get this worked.
You could use FIND_IN_SET:
SELECT t.first_name
FROM `User` `t`
WHERE FIND_IN_SET('50', `keywords`) > 0
AND FIND_IN_SET('52', `keywords`) > 0
AND FIND_IN_SET('53', `keywords`) > 0
AND FIND_IN_SET('51', `keywords`) = 0;
Keep in mind it could be slow. The correct way is to normalize your table structure.
FIND_IN_SET will do the job for you but it does not use indexes. This is not a bug it's a feature.
SUBSTRING_INDEX can use an index and return the data as you wish. You don't have an index on it at the moment, But the catch here is that TEXT fields cannot be fully indexed and what you have is a TEXT field.
Normalize!
This is what you really should be doing. It's not a good idea to store comma separated values in a database. You really should be having a keywords table and since the keywords will be short, you can have a char or varchar narrow column which can be fully indexed.

MySQL WHERE Condition on integer field returning incorrect values

I'm having a problem with MySQL returning the incorrect result when applying a WHERE condition to an integer field with a string value.
CREATE TABLE `people` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
INSERT INTO `people` (`id`, `name`)
VALUES
(1, 'Bob'),
(2, 'Sally'),
(3, 'Jim');
Now when I run the query:
SELECT *
FROM people
WHERE id = '1-abcd';
My result set is:
id name
1 Bob
MySQL appears to be truncating the string value '1-abcd' to '1' behind the scenes as soon as it hits a non-integral character (in the conversion from a string to INT).
You're probably wondering why this matters. I'm trying to fix a site for a PCI compliance scan. The scan thinks the URI '/some/page?id=102-1' is allowing some form of sequel injection, but in reality it's showing the same content at '/some/page?id=102'.
This is not an issue in one place. It is an issue all over the place, and it's a fairly large system. Is there some way to rectify this on the MySQL end of things, so it no longer mistakenly judges the two values to be equivalent? I looked at the documentation for SQL modes, but didn't see anything regarding this circumstance.
UPDATE: I filed a dispute with the company that produced the scan, which they accepted, so I'm no longer in the woods. But it is disappointing that there's apparently no way to configure the casting behavior of MySQL from a string to INT in this case. (You can, but only for INSERTs and UPDATEs.)
What happens that MySQL type-casts the string literal value to an integer, and when it does that it starts from the left of the string and as soon as it reaches a character that cannot be considered part of a number, it strips out everything from that point on. So 1-0 gives output matching to 1. To do this you can use cast. I am not 100% sure about the syntax but it is like this:
select * from people
where id =
(
case when ISNUMERIC( '1-0' )
then cast ('1-0' as int)
else null
end )
What this will do is that if it is an numeric value then it will return the correct matching row or else not.
Edit:
The above query seems to be of MSSQL/Oracle and would not work with MySQL. For MySQL you can use RegExp. I have never use one but you can find more details here:
http://mysqlhints.blogspot.in/2012/01/how-to-find-out-if-entire-string-is.html
http://www.ash.burton.fm/blogs/2010/12/quick-tip-mysql-equivalent-of-isnumeric
http://www.justskins.com/forums/how-to-use-isnumeric-137604.html

Bug in sqlfiddle OR I don't understand INSERT ... ON DUPLICATE KEY UPDATE

This sqlfiddle link seems to retain state across invocations:
http://sqlfiddle.com/#!2/125bc/1
It contains this schema for mysql:
CREATE TABLE if not exists `standings` (
`teamid` int(11) NOT NULL,
`win` decimal(23,0) default NULL,
`tie` decimal(23,0) default NULL,
`lose` decimal(23,0) default NULL,
PRIMARY KEY (`teamid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `standings` (`teamid`, `win`, `tie`, `lose`) VALUES
(1, 3, 0, 0),
(2, 1, 1, 1),
(3, 1, 1, 1),
(4, 0, 0, 3);
CREATE TABLE if not exists `newscores` (
`recordid` int(11) NOT NULL auto_increment,
`teamid` int(11) NOT NULL,
`gameid` int(11) NOT NULL,
`totalstrokes` int(11) NOT NULL,
primary key (recordid)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `newscores` (`recordid`, `teamid`, `gameid`, `totalstrokes`) VALUES
(5, 1, 1, 145),
(6, 2, 1, 105),
(7, 5, 1, 145),
(8, 6, 1, 155);
and these two queries:
Insert into standings (teamid, win, tie, lose) (SELECT g1.teamid, SUM( IF( g1.totalstrokes < g2.totalstrokes, 1, 0 ) ) AS win, SUM( IF( g1.totalstrokes = g2.totalstrokes, 1, 0 ) ) AS tie, SUM( IF( g1.totalstrokes > g2.totalstrokes, 1, 0 ) ) AS lose
FROM newscores g1
JOIN newscores g2 ON g1.gameid = g2.gameid
AND g1.teamid != g2.teamid
GROUP BY g1.teamid)
on duplicate key
update win = win + values(win),
lose = lose + values(lose),
tie = tie + values(tie);
select * from standings;
It should result in this standings table:
teamid win tie lose
1 4 1 1
2 4 1 1
3 1 1 1
4 0 0 3
5 1 1 1
6 0 0 3
and it does, the first time it's run. The second time it's run (by pasting the url into a new window), some of the values for teamids 1,2,5,6 are incremented.
I can reset it by editing the schema to change "create table" to "create if not exists table" and vice versa, or including "drop table" statements. But this seems very odd.
PS I'd be grateful if someone more pointful than I added a sqlfiddle tag to this question.
I'm the author of SQL Fiddle. There is a very simple explanation for this behavior. Essentially, all of your queries that you run on the right-side panel (the "Run Query" side) are executed in a transaction block, which is immediately rolled back to preserve the state of the schema (as defined by the left-side panel). Most of the time, everything is returned to exactly where things started, because most everything that was executed in a transaction can be rolled back. However, as I discovered early on with SQL Fiddle, one of the few things that doesn't get rolled back is auto incrementing ID values. This is an intentional design decision made by all of the vendors, and it is meant to ensure that your primary keys will never collide from reuse.
Since auto ids are supposed to be meaningless, it never really struck me as a problem for SQL Fiddle that this one thing changes (particularly since most people run their inserts on the left-side anyway).
You can see this behavior without having to open multiple windows, BTW - just hit "Run Query" multiple times and you'll see it change. You can also see it with my sample fiddle for SQL Server: http://sqlfiddle.com/#!3/1fa93/1 Just run that query multiple times and you'll see the id change each time. (It will reset if the fiddle hasn't been used in a while, since I drop the running DB to free up memory after a particular fiddle goes unused).
Edit
Doh! Sorry, was not reading your query closely enough. I now see what's going on. You are using MyISAM tables instead of InnoDB. I really need to disable those as an option for MySQL. You see, they don't support transactions at all. So when I attempt to roll back your updates to those tables, well, the updates simply don't get rolled back. You keep incrementing them. I saw this when I first rolled out MySQL as an option, since by default MySQL uses MyISAM. I had to change the default to InnoDB to get transactions working.
Here you can see it working fine when I simply removed your explicit use of MyISAM: http://sqlfiddle.com/#!2/cec6e/1
Update
Here is the version that I've re-arranged slightly, due to some changed requirements for MySQL: http://sqlfiddle.com/#!2/a9cc3/1