2013-04-23 4 views
1

Я пытаюсь найти продукты, имеющие определенные спецификации. Из-за сложных комбинаций спецификаций у меня есть другая таблица, которая является отношением n: m к другой таблице.Несколько статей n: m

product 
id | other data ... 
---+--------------- 
1 | bike 
2 | bus 
3 | car 

product_spec 
product_id | spec_id 
-----------+--------------- 
1   | 1 
1   | 2 
1   | 3 
2   | 1 
2   | 3 
2   | 4 
3   | 2 
3   | 4 

Теперь мне нужно найти продукт с определенными характеристиками. Это хорошо работает, если у меня есть список спецификаций которых продукт все должны иметь:

SELECT p.id FROM product p, product_spec s 
WHERE p.id = s.product_id AND s.spec_id IN (1, 2, 3) 
GROUP BY p.id HAVING COUNT(p.id) = 3 

(с 3-числом спецификаций, что продукт должен иметь) дает продукту 1

SELECT p.id FROM product p, product_spec s 
WHERE p.id = s.product_id AND s.spec_id IN (1, 3) 
GROUP BY p.id HAVING COUNT(p.id) = 2 

дает продукт 1 и 2. До сих пор так хорошо. Теперь приходит беда:

Что делать, если я хочу, чтобы все продукты, которые имеют спецификации 1 и имеет либо спецификация 2 или 4.

SELECT p.id FROM product p, product_spec s 
WHERE p.id = s.product_id AND 
    (s.spec_id = 1 OR s.spec_id IN (2, 4)) 
GROUP BY p.id HAVING COUNT(p.id) = 2 

(явно) возвращает продукт 1 и 3, но 3 ошибочно, потому что у него есть как spec 2, так и 4, но не 1.

Я думал дать разные значения предложений spec (например, группа spec 1 = 1, группа spec 2 = 2 (группа spec 3 = 4 и т. Д.).)), добавьте их и используйте HAVING SUM(extra_field) = 3, но я не увенчался успехом так.

Итак, как можно сделать такой запрос? Должен ли я прибегать к нескольким запросам (и если, какой был бы лучший подход)?

Я работаю с MySQL, но я предполагаю, что вопрос не ограничивается одной системой.

Вот заявление воссоздать эти тестовые таблицы:

CREATE TABLE product (
    id int(11) unsigned NOT NULL AUTO_INCREMENT, 
    title varchar(20) NOT NULL, 
    PRIMARY KEY (id) 
); 
INSERT INTO product (id, title) VALUES (1, 'bike'), (2, 'bus'), (3, 'car'); 
CREATE TABLE product_spec (
    product_id int(10) unsigned NOT NULL, 
    spec_id int(10) unsigned NOT NULL, 
    PRIMARY KEY (product_id,spec_id) 
); 
INSERT INTO product_spec (product_id, spec_id) VALUES (1, 1), (1, 2), (1, 3), (2, 1), (2, 3), (3, 2), (3, 4); 
+0

+1 для добавления сценария для тестовых данных –

ответ

1

Вы можете использовать SUM + СЛУЧАЙ для вычисления суммы для отдельной «категории» и использовать комбинированную HAVING запрос:

SELECT p.id 
FROM 
    product p, 
    product_spec s 
WHERE p.id = s.product_id 
GROUP BY p.id 
HAVING 
    SUM(case when s.spec_id = 1 then 1 else 0 end) > 0 and 
    SUM(case when s.spec_id in (2,4) then 1 else 0 end) > 0 
+0

Удивительный. Это по моей мысли, но я не смог поместить ее в SQL. Благодаря! – akirk