选择MySQL中列表的子集

时间:2010-02-15 02:04:35

标签: mysql select

我是一个很好的人,我有两个表:“产品”和“产品属性”。

这是一些虚构的数据(实际的东西涉及更多的表格)

产品表:

product_id | product_name                  
10         |   aaa                           
11         |   bbb   
12         |   ccc

产品属性表:

attribute_id | product_id
      21     |    10         
      23     |    10         
      24     |    10         
      21     |    11         
      24     |    11         
      21     |    12         
      25     |    12         

每个产品都有多个可能的属性。我有一个属性ID列表,如(21,10,25),我需要选择其属性是该列表子集的所有产品。

是否可以在一个查询中执行此操作?

当我过滤(21,24)时,所需的输出仅返回产品11(bbb)

当我过滤(21,23,24)时,所需的输出是返回产品10和11.

当我过滤(21)时,所需的输出将返回none(因为所有产品至少有一个其他属性)。

7 个答案:

答案 0 :(得分:5)

如果您假装过滤器在表格中:

select * 
from product p
where not exists (
    select 1
    from attributes a
    where a.product_id = p.product_id
    and not exists(
        select 1
        from filter f
        where f.id_attribute = a.id_attribute))

如果它在构造的查询中:

select * 
from product p
where not exists (
    select 1
    from attributes a
    where a.product_id = p.product_id
    and attribute_id not in (<list>))

这不是我的头脑,所以可能有拼写错误。

答案 1 :(得分:1)

假设您的产品表名为Product,该表中的ID列名为Id:

SELECT * from Product p where p.Id IN 
  (Select id_product from ProductAttributes where id_attribute in (21, 23, 24))

答案 2 :(得分:1)

select
    P.id,
    P.name,
    count(P.id) as matched_attr_count,
    count(PA.a_id) as total_attr_count
from
    product_attributes PA
    left join product P on P.id = PA.p_id and PA.a_id in (21,23,24)
group by
    PA.p_id
having
    matched_attr_count = total_attr_count;

答案 3 :(得分:1)

这应该只返回那些id,其中每个id的所有属性都完全包含在列表中:

select attribute_match.id_product from
 (select id_product, count(*) c from attributes
  where id_attribute in (21, 10, 25)
  group by id_product) attribute_match,
 (select id_product, count(*) c_count from attributes
  group by id_product) attribute_total
where attribute_match.id_product = attribute_total.id_product
      and attribute_match.c = attribute_total.c

答案 4 :(得分:1)

在MySQL支持EXCEPT查询组合之前,

SELECT product_id
  FROM attributes
  WHERE product_id NOT IN (
       SELECT product_id
         FROM attributes 
         WHERE attribute_id NOT IN (21, 23, 24)
     )
  GROUP BY product_id
UNION
SELECT id 
  FROM products AS p
  LEFT JOIN attributes AS a
    ON p.id = a.product_id
  WHERE a.product_id IS NULL

如果您希望只拥有具有所有给定属性的产品,请在第一个外部查询中添加HAVING COUNT(*)=n子句,其中“n”是属性列表的长度。

答案 5 :(得分:0)

基于你的洞察力,我进一步优化了它,并且只使用了1 COUNT语句:

SELECT * ,COUNT(p.product_id) AS c FROM product_attribute pa 
LEFT JOIN products p ON pa.product_id = p.product_id AND pa.attribute_id NOT IN ($filter_list)
GROUP BY pa.product_id
HAVING c=0

有用吗? :)

编辑:
  该代码不会返回产品的名称或其他可能包含的字段。这是正确的:

SELECT * ,COUNT(pa.product_id ) AS c FROM products p
LEFT JOIN product_attribute pa ON pa.product_id = p.product_id AND pa.attribute_id NOT IN ($filter)
GROUP BY p.product_id
HAVING c=0

答案 6 :(得分:-1)

让我发布简单的虚数据(实际的东西涉及更多的表)

产品

product_id | product_name                  
10          |   aaa                           
11     |    bbb  

product_attribute

attribute_id | product_id  <br>
21     |    10         
23     |    10         
24     |    10         
21     |    11         
24     |    11 

我想要那个:

  • 当我过滤(21,24)仅返回产品11(bbb)
  • 当我过滤(21,23,24)以返回两个产品时
  • 当我过滤(21)时只返回无(因为没有产品只有该属性)