web-dev-qa-db-fra.com

SWITCH avec LIKE dans la requête SELECT dans MySQL

J'ai ce tableau de balises

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');

Je veux récupérer tous les enregistrements où la balise correspond aux mots clés class ou pack ou new, ainsi qu'un autre champ qui indique lequel des 3 mots clés correspond réellement au champ de balise.

La requête suivante ne donne pas de résultats corrects Requête 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%"

Je dois utiliser le même à l'intérieur du boîtier. Sinon, complétez les travaux de correspondance. La requête suivante fonctionne: -

Requête 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"

Quel est le problème avec la requête 1. Veuillez aider.

26
Sandeepan Nath

Mysql prend en charge deux variantes de casse, celle que vous utilisez dans la requête 2 est moins flexible mais ne prend en charge que l'égalité sur une seule variable. L'autre version ne spécifie aucune variable après la casse et les conditions ne doivent pas être uniquement égales:

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%"

Voir documentation pour plus de détails

EDIT: Voici un peu plus d'explications sur les raisons pour lesquelles votre requête # 1 a renvoyé ce qu'elle a retourné:

case tag
   when tag LIKE "%class%" then "class" 
   when tag LIKE "%new%" then "new"
   when tag LIKE "%pack%" then "pack"
end as matching_tag

s'attend à obtenir une valeur littérale pour la comparaison entre when ... then Dans le cas ci-dessus, les expressions tag LIKE "%class%", tag LIKE "%new%" et tag LIKE "%pack%" sont tous évalués avant la comparaison réelle des cas. Cependant (!), Ce qui se passe, c'est qu'ils deviennent 0 ou 1 et par rapport à la valeur de tag, c'est la première valeur de 0 qui correspondra à n'importe quel caractère (le caractère sera converti en 0) - cela est cohérent avec les résultats de votre première requête.

Voici une requête qui affiche les valeurs logiques des expressions pertinentes:

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%";

C'est pourquoi vous obtenez des résultats inattendus; le CAST silencieux est un écueil standard ici.

37
Unreason

Je veux juste rappeler, à propos de la clause else:

case  
   when tag LIKE "%class%" then "class" 
   when tag LIKE "%new%" then "new"
   when tag LIKE "%pack%" then "pack"
   else "no one"
end as matching_tag 
13
Vladimir Kovpak