MySQL « Выборка строк из таблицы по нескольким значениям
Есть две таблицы,
с товарами
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`price` float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=136 DEFAULT CHARSET=utf8 AUTO_INCREMENT=136 ;
и с характеристиками
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
CREATE TABLE `extra_value` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`item_id` int(11) NOT NULL DEFAULT '0',
`value_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2531 DEFAULT CHARSET=utf8 AUTO_INCREMENT=2531 ;
У каждого товара есть несколько характеристик в таблице extra_value.
Необходимо вывести позиции соответсвующее нескольким характеристикам (т.е.
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
WHERE extra_value.value_id IN (10, 11, 12)
).
с товарами
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`price` float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=136 DEFAULT CHARSET=utf8 AUTO_INCREMENT=136 ;
и с характеристиками
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
CREATE TABLE `extra_value` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`item_id` int(11) NOT NULL DEFAULT '0',
`value_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2531 DEFAULT CHARSET=utf8 AUTO_INCREMENT=2531 ;
У каждого товара есть несколько характеристик в таблице extra_value.
Необходимо вывести позиции соответсвующее нескольким характеристикам (т.е.
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
WHERE extra_value.value_id IN (10, 11, 12)
1 ответов
Конкретно для вашего случая я бы предложил такой вариант. Тут для каждого итема отбирается три строки, в группировке по итемам считаем сколько различных value_id насобиралось (в данном случае больше 3-х быть не может). Полученный список нужных id-шников можно использовать для выборки из таблицы. Если их много, то конструкцию in лучше заменить на соединение join.
В любом случае недостатков море - двойное чтение таблицы итемов, группировка.
SELECT * FROM `items`
WHERE `id` in (
SELECT `item_id`
FROM `extra_value`
WHERE `value_id` IN (10, 11, 12)
GROUP BY `item_id`
HAVING count(distinct `value_id`) = 3
);
SELECT `i`.* FROM `items` `i`
LEFT JOIN `extra_value` `ev` ON `i`.`id` = `ev`.`item_id`
WHERE `ev`.`value_id` IN (10, 11, 12)
GROUP BY `i`.`id`
Если надо выбрать items только те, у которых есть все три характеристики, то
SELECT `i`.* ,
MAX(CASE WHEN ev.value_id = 10 THEN 1 END) AS has_value_10,
MAX(CASE WHEN ev.value_id = 11 THEN 1 END) AS has_value_11,
MAX(CASE WHEN ev.value_id = 12 THEN 1 END) AS has_value_12
FROM `items` `i`
INNER JOIN `extra_value` `ev` ON `i`.`id` = `ev`.`item_id`
AND `ev`.`value_id` IN (10, 11, 12)
GROUP BY `i`.`id`
HAVING has_value_10 IS NOT NULL
AND has_value_11 IS NOT NULL AND has_value_12 IS NOT NULL
Если же надо показывать все items, то меняем INNER JOIN на LEFT JOIN и убираем HAVING