2013-04-23 54 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錯誤,因爲它確實同時具有規格2和4但不是1.

我在考慮給出不同的spec子句值(如規格組1 = 1,規格組2 = 2(規格組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爲測試數據添加腳本 – 2013-04-23 11:37:22

回答

1

你可以用SUM + CASE來計算個人「類別」的數額和使用結合而具有查詢:

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 2013-04-23 12:17:35