One possible optimization is to define [column d] as the type of SET . As the documentation says :
MySQL stores the SET values ββnumerically, with the least significant bit being the stored value corresponding to the first set. If you are SET in a digital context, the resulting value has bits set corresponding to the given members that make up the column value.
Here is a quick and easy example:
CREATE TABLE `tbl_name` ( `id` int(11) NOT NULL AUTO_INCREMENT, `set_col` set('a','b','c','d') NOT NULL, PRIMARY KEY (`id`), KEY `set_col_idx` (`set_col`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `tbl_name` (`set_col`) VALUES ('a'), ('b'), ('c'), ('d'), ('a,b'), ('a,c'), ('a,d'), ('b,c'), ('b,d'), ('c,d'), ('a,b,c'), ('a,b,d'), ('a,c,d'), ('b,c,d'), ('a,b,c,d');
The set_col column specified as SET('a','b','c','d') has members with the following decimal and binary values:
ββββββββββββββ¦ββββββββββββββββ¦βββββββββββββββ β SET Member β Decimal Value β Binary Value β β βββββββββββββ¬ββββββββββββββββ¬βββββββββββββββ£ β 'a' β 1 β 0001 β β βββββββββββββ¬ββββββββββββββββ¬βββββββββββββββ£ β 'b' β 2 β 0010 β β βββββββββββββ¬ββββββββββββββββ¬βββββββββββββββ£ β 'c' β 4 β 0100 β β βββββββββββββ¬ββββββββββββββββ¬βββββββββββββββ£ β 'd' β 8 β 1000 β ββββββββββββββ©ββββββββββββββββ©βββββββββββββββ
So, if you need to extract records with the value a,c,d , this is the first, third and fourth member, which is 1 + 4 + 8 , which is 13 .
If you run the query:
EXPLAIN SELECT * FROM `tbl_name` WHERE `tbl_name`.`set_col` = 13;
You'll get:
ββββββ¦ββββββββββββββ¦βββββββββββ¦βββββββ¦ββββββββββββββββ¦ββββββββββββββ¦ββββββββββ¦ββββββββ¦βββββββ¦ββββββββββββββ β id β select_type β table β type β possible_keys β key β key_len β ref β rows β Extra β β βββββ¬ββββββββββββββ¬βββββββββββ¬βββββββ¬ββββββββββββββββ¬ββββββββββββββ¬ββββββββββ¬ββββββββ¬βββββββ¬ββββββββββββββ£ β 1 β SIMPLE β tbl_name β ref β set_col_idx β set_col_idx β 1 β const β 1 β Using index β ββββββ©ββββββββββββββ©βββββββββββ©βββββββ©ββββββββββββββββ©ββββββββββββββ©ββββββββββ©ββββββββ©βββββββ©ββββββββββββββ
You do not need to manually find the decimal values ββof the SET parameters - you can use SUM , for example:
SELECT * FROM `tbl_name` WHERE `set_col` = (SELECT SUM(`set_col`) FROM `tbl_name` WHERE `set_col` IN ('a', 'c', 'd') );
ββββββ¦ββββββββββββββ¦βββββββββββ¦ββββββββ¦ββββββββββββββββ¦ββββββββββββββ¦ββββββββββ¦ββββββββ¦βββββββ¦βββββββββββββββββββββββββββ β id β select_type β table β type β possible_keys β key β key_len β ref β rows β Extra β β βββββ¬ββββββββββββββ¬βββββββββββ¬ββββββββ¬ββββββββββββββββ¬ββββββββββββββ¬ββββββββββ¬ββββββββ¬βββββββ¬βββββββββββββββββββββββββββ£ β 1 β PRIMARY β tbl_name β index β set_col_idx β set_col_idx β 1 β NULL β 15 β Using where; Using index β β βββββ¬ββββββββββββββ¬βββββββββββ¬ββββββββ¬ββββββββββββββββ¬ββββββββββββββ¬ββββββββββ¬ββββββββ¬βββββββ¬βββββββββββββββββββββββββββ£ β 1 β SUBQUERY β tbl_name β range β set_col_idx β set_col_idx β 1 β NULL β 3 β Using where; Using index β ββββββ©ββββββββββββββ©βββββββββββ©ββββββββ©ββββββββββββββββ©ββββββββββββββ©ββββββββββ©ββββββββ©βββββββ©βββββββββββββββββββββββββββ