2016-12-01 48 views
1

問:
我怎麼會碰到一些Red和大小S所有產品? 這將意味着我只得到產品2: Product (color:green,red => size:S)MySQL的產品獲得多個過濾值

說明:
我遇到一個問題,選擇產品已應用特定的過濾器的數據庫。在下面你會發現我的表格,看到SQLfiddle爲真正的SQL。

product

id | title 
------------------------------ 
1 | Product (color:green => size:S) 
2 | Product (color:green,red => size:S) 
3 | Product (color:red) 

filter

id | name 
------------ 
1 | Color 
2 | Size 

filter_value

id | filter_id | name 
--------------------- 
1 |   1 | green 
2 |   1 | red 
3 |   2 | S 

product_filter_value

id | product_id | filter_id | filter_value_id 
--------------------------------------------- 
1 |   1 |   1 |    1 
2 |   1 |   2 |    3 
3 |   2 |   1 |    1 
4 |   2 |   1 |    2 
5 |   2 |   2 |    3 
6 |   3 |   1 |    2 

要選擇與過濾值red所有產品,我運行此查詢:

# ALL COLOR RED 
SELECT p.* 
FROM product p 
    LEFT JOIN product_filter_value pfv ON p.id = pfv.product_id 
WHERE (pfv.filter_id IN ('1')) 
    AND (pfv.filter_value_id IN ('2')) 
GROUP BY p.id 
LIMIT 10 OFFSET 0; 

要選擇與過濾值S所有產品,我運行此查詢:

# ALL SIZE S 
SELECT p.* 
FROM product p 
    LEFT JOIN product_filter_value pfv ON p.id = pfv.product_id 
WHERE (pfv.filter_id IN ('2')) 
    AND (pfv.filter_value_id IN ('3')) 
GROUP BY p.id 
LIMIT 10 OFFSET 0; 

但如何我會得到所有產品是Red和大小S? 這意味着我只能得到產品2: Product (color:green,red => size:S)

回答

1

我不能讓sql小提琴工作,但我想我會給這個鏡頭無論如何。您可能必須爲不同的過濾器類型提供不同的連接。與表的別名pfv1的加入是過濾器1,和pfv2是過濾器2

SELECT * 
FROM product p 
    LEFT JOIN product_filter_value pfv1 ON p.id = pfv1.product_id and pfv1.filter_id = 1 
    LEFT JOIN product_filter_value pfv2 ON p.id = pfv2.product_id and pfv2.filter_id = 2 
WHERE (pfv1.filter_id IN ('1')) 
    AND (pfv1.filter_value_id IN ('2')) 
    and (pfv2.filter_id IN ('2')) 
    AND (pfv2.filter_value_id IN ('3')) 
GROUP BY p.id 
LIMIT 10 OFFSET 0; 

這可能是有趣的,看看整套沒有where條款:

SELECT * 
FROM product p 
    LEFT JOIN product_filter_value pfv1 ON p.id = pfv1.product_id and pfv1.filter_id = 1 
    LEFT JOIN product_filter_value pfv2 ON p.id = pfv2.product_id and pfv2.filter_id = 2 

+ ------- + ----------------------------------- + ------- + --------------- + -------------- + -------------------- + ------- + --------------- + -------------- + -------------------- + 
| id  | title        | id  | product_id  | filter_id  | filter_value_id  | id  | product_id  | filter_id  | filter_value_id  | 
| 1  | Product (color:green => size:S)  | 1  | 1    | 1    | 1     | 2  | 1    | 2    | 3     | 
| 2  | Product (color:green,red => size:S) | 3  | 2    | 1    | 1     | 5  | 2    | 2    | 3     | 
| 2  | Product (color:green,red => size:S) | 4  | 2    | 1    | 2     | 5  | 2    | 2    | 3     | 
| 3  | Product (color:red)     | 6  | 3    | 1    | 2     |   |     |    |      | 
+ ------- + ----------------------------------- + ------- + --------------- + -------------- + -------------------- + ------- + --------------- + -------------- + -------------------- + 
4 rows 

產品2有兩條記錄,因爲它有兩種顏色,而產品3沒有最後四列的值,因爲它沒有尺寸屬性。

+0

SQL小提琴確實打破發現,似乎沒有這麼好的服務。你的第一個例子似乎工作正常。我不確定你的第二個。我仍然需要filter_value_id參與。 – Timo002

+0

第二個示例僅用於深入瞭解沒有過濾器會發生什麼情況。很高興第一個適合你。 – CGritton

0

你可以得到2組單獨的元素,加入他們的行列,然後篩選它們(在一個易於閱讀Word格式)

給(和你的SQL小提琴不通過的方式加載)

/* 
drop table if exists product; 
create table product(id int ,title varchar(50)); 
insert into product values 
(1 , 'Product (color:green => size:S)'), 
(2 , 'Product (color:green,red => size:S)'), 
(3 , 'Product (color:red)'); 

drop table if exists filter; 
create Table filter(id int, name varchar(5)); 
insert into filter values 
(1 , 'Color'), 
(2 , 'Size'); 

drop table if exists filter_value; 
create table filter_value(id int, filter_id int, name varchar(5)); 
insert into filter_value values 
(1 ,   1 , 'green'), 
(2 ,   1 , 'red'), 
(3 ,   2 , 'S'); 

drop table if exists product_filter_value; 
create Table product_filter_value(id int, product_id int, filter_id int, filter_value_id int); 
insert into product_filter_value values 
(1 ,   1 ,   1 ,    1), 
(2 ,   1 ,   2 ,    3), 
(3 ,   2 ,   1 ,    1), 
(4 ,   2 ,   1 ,    2), 
(5 ,   2 ,   2 ,    3), 
(6 ,   3 ,   1 ,    2); 
*/ 

子查詢就會越來越顏色和子查詢牛逼得到大小

select u.stitle product 
from 
(
select s.* , t.* from 
(
select p.id sid,p.title stitle,fv.name sfvname,f.name sname 
from product p 
join product_filter_value pfv on pfv.product_id = p.id 
join filter_value fv on fv.id = pfv.filter_value_id 
join filter f on f.id = fv.filter_id 
where f.name = 'color' 
) s 
join 
(
select p.id tid,p.title ttitle,fv.name tfvname,f.name tfname 
from product p 
join product_filter_value pfv on pfv.product_id = p.id 
join filter_value fv on fv.id = pfv.filter_value_id 
join filter f on f.id = fv.filter_id 
where f.name = 'size' 
) t on s.stitle = t.ttitle 
) u 
where u.sname = 'color' and u.sfvname = 'red' and u.tfname = 'Size' and u.tfvname = 'S' 
+0

SQLfiddle確實有效,但現在它對我來說也是破碎的。我總是有SQLfiddle的問題。 – Timo002

0

讓我們開始尋找一兩件事簡單的基礎。 它可能是尺寸,顏色或其他任何您的真實數據。 查詢可能是

SELECT 
     pfv.product_id, 
     f.name 
    from 
     product_filter_value pfv 
     join filter_value fv 
      ON pfv.filter_value_id = fv.id 
       AND fv.name = "what you are looking for" 
     JOIN filter f 
      ON pfv.filter_id = f.id 

現在,你可以爲每個唯一的在同一個查詢加入做多。 我將後綴每個獨特的東西被過濾的別名表。 你甚至可以添加如果是適用的由其他子查詢加盟一個品牌,如ProdBrand別名現在

SELECT 
     p.product_id, 
     p.title, 
     ProdColor.name as Color, 
     ProdSize.name as Size 
    from 
     Product p 
     JOIN (select 
         pfv.Product_id, 
         fv.name 
        from 
         product_filter_value pfv 
         JOIN filter_value fv 
          ON pfv.filter_value_id = fv.id 
          AND fv.name = "red" 
         JOIN filter f 
          ON pfv.filter_id = f.id 
          AND f.name = "Color") ProdColor 
      ON P.id = ProdColor.Product_ID 
     JOIN (select 
         pfv.Product_id, 
         fv.name 
        from 
         product_filter_value pfv 
         JOIN filter_value fv 
          ON pfv.filter_value_id = fv.id 
          AND fv.name = "S" 
         JOIN filter f 
          ON pfv.filter_id = f.id 
          AND f.name = "Size") ProdSize 
      ON P.id = ProdSize.Product_ID 

,如果你想嘗試多種顏色或大小, 只是改變每個子查詢的標準,像..

AND INLIST(fv.name, "red", "blue") -- example for red OR blue 

AND INLIST(fv.name, "S", "M") -- example for Small OR Medium 

這可能是一個很長的查詢,但是單獨看每一塊很簡單。它的目的是顏色,尺寸,品牌等等的標準。您只是將其作爲獲取產品的整體條件的一部分加入其中。

我從您的原始模式工作SQLFiddle可以在this working sample

+0

我沒有測試過你的查詢。 CGritton的答案似乎簡單得多。我不確定表現。另一方面,您可以使用篩選器名稱而不是ID進行查詢。 – Timo002