I have this Tags table
CREATE TABLE IF NOT EXISTS `Tags` ( `id_tag` int(10) unsigned NOT NULL auto_increment, `tag` varchar(255) default NULL, PRIMARY KEY (`id_tag`), UNIQUE KEY `tag` (`tag`), KEY `id_tag` (`id_tag`), KEY `tag_2` (`tag`), KEY `tag_3` (`tag`), KEY `tag_4` (`tag`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2937 ; INSERT INTO `Tags` (`id_tag`, `tag`) VALUES (1816, '(class'), (2642, 'class\r\n\r\nâ?¬35'), (1906, 'class\r\nif'), (1398, 'class'), (2436, 'class)'), (1973, 'class:\n1.'), (2791, 'classes'), (1325, 'New'), (2185, 'pack'), (1905, 'packed'), (1389, 'WebClass');
I want to fetch all records where tag matches keywords class
or pack
or new
, along with another field which indicates which of the 3 keywords actually matched with the tag field.
The following query does not give correct results Query 1
select id_tag, case tag when tag LIKE "%class%" then "class" when tag LIKE "%new%" then "new" when tag LIKE "%pack%" then "pack" end as matching_tag from Tags where tag LIKE "%class%" OR tag LIKE "%new%" OR tag LIKE "%pack%"
I have to use the like inside the case. Otherwise complete matching works. The following query works:-
Query 2
select id_tag, case tag when "class" then "class" when "new" then "new" when "pack" then "pack" end as matching_tag from Tags where tag = "class" OR tag = "new" OR tag = "pack"
What is wrong with the query 1. Please help.
Mysql supports two variants of case, the one you use in query 2 is less flexible but supports only equality on a single variable. The other version specifies no variable after case and then conditions need not be only equality:
select id_tag, case when tag LIKE "%class%" then "class" when tag LIKE "%new%" then "new" when tag LIKE "%pack%" then "pack" end as matching_tag from Tags where tag LIKE "%class%" OR tag LIKE "%new%" OR tag LIKE "%pack%"
See documentation for further details
EDIT: Here's a bit more explanation on why your query #1 returned what it returned:
case tag when tag LIKE "%class%" then "class" when tag LIKE "%new%" then "new" when tag LIKE "%pack%" then "pack" end as matching_tag
expects to get a literal value for comparison between when ... then
In the above case the expressions tag LIKE "%class%"
, tag LIKE "%new%"
and tag LIKE "%pack%"
are all evaluated before the actual case comparison. However (!), what happens is that they become either 0 or 1 and when compared to the value of tag it is the first value of 0 that will match any char (char will get cast to 0) - this is consistent with the results of your first query.
Here's a query that shows the logical values for the relevant expressions:
select id_tag, tag LIKE "%class%", tag LIKE "%new%", tag = 0, case tag when tag LIKE "%class%" then "class" when tag LIKE "%new%" then "new" when tag LIKE "%pack%" then "pack" end as matching_tag from Tags where tag LIKE "%class%" OR tag LIKE "%new%" OR tag LIKE "%pack%";
That's why you get unexpected results; the silent CAST is a standard pitfall here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With