MySQL获得具有多个过滤器值的产品

时间:2016-12-01 12:04:48

标签: mysql

问题:
我如何获得Red和尺寸S的所有产品? 这意味着我只获得产品2: Product (color:green,red => size:S)

说明
我从使用某些过滤器的数据库中选择产品时遇到了问题。您可以在下面找到我的表格,并查看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)

3 个答案:

答案 0 :(得分:1)

我无法让sql小提琴工作,但我还是认为我还是试一试。您可能必须为不同的筛选器类型具有不同的连接。表别名pfv1的连接用于filter1,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没有最后四列的值,因为它没有大小属性​​。

答案 1 :(得分:0)

您可以单独获取2个元素,加入它们然后过滤它们(以易于阅读的单词格式)

给出(并且你的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'

答案 2 :(得分: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

这可能是一个很长的查询,但单独查看每个部分非常简单。它的目的是一个标准,颜色,尺寸,品牌等。您只是加入它作为您获得产品的整体条件的一部分。

我可以在this working sample

找到原始模式中的SQLFiddle