web-dev-qa-db-ja.com

MySQLのSELECTクエリ内でLIKEを使用したSWITCH

このタグ表があります

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

タグがキーワードclassまたはpackまたはnewに一致するすべてのレコードと、3つのキーワードのどれが実際にタグフィールドに一致したかを示す別のフィールドを取得したい。

次のクエリでは正しい結果が得られませんクエリ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%"

私はケースの中に同じようなものを使わなければなりません。それ以外の場合は、完全に一致します。次のクエリが機能します:-

クエリ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"

クエリ1の何が問題なのか、助けてください。

26
Sandeepan Nath

Mysqlは2つのケースのバリアントをサポートします。クエリ2で使用するものは柔軟性が劣りますが、単一の変数での等価性のみをサポートします。もう1つのバージョンでは、大文字小文字の後に変数を指定しないため、条件は等値だけである必要はありません。

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

詳細については documentation を参照してください

編集:クエリ#1が返したものを返した理由についてもう少し説明します。

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

when ... thenを比較するためのリテラル値を取得する必要があります。上記の場合、式tag LIKE "%class%"tag LIKE "%new%"およびtag LIKE "%pack%"はすべて、実際のケース比較の前に評価されます。ただし(!)、何が起こるかは、それらが0または1になり、タグの値と比較すると、charに一致する最初の値0になります(charは0にキャストされます)-これは結果と一致します最初のクエリの。

関連する式の論理値を示すクエリは次のとおりです。

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

そのため、予期しない結果が生じます。ここでは、サイレントCASTが標準的な落とし穴です。

37
Unreason

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