MySQL几个内部联接vs子查询

时间:2015-10-07 10:06:33

标签: php mysql join subquery

我在使用PHP构建查询时无法简化复杂查询。

我的问题:

产品可以具有多种属性,例如。颜色,大小和状态。 要获得具有所有3种属性的产品,我可以:

products p

INNER JOIN product_propeties p1 on p.pid = p1.pid AND p1.property = 1 (color)

INNER JOIN product_propeties p2 on p.pid = p2.pid AND p2.property = 2 (size)

INNER JOIN product_propeties p3 on p.pid = p3.pid AND p3.property = 3 (state)

这很好用。我会得到所有这3个属性的产品。

我现在的问题是我不想用PHP生成p1,p2,p3。属性列在表" property_groups"中。在此表中,我可以对属性进行分组。

proberty|title|group_name

1|color|winterspecial

2|size|winterspecial

3|state|winterspecial

我想加入" property_groups"表" winterspecial"而我从上面的例子我不知道如何。问题是每个属性都需要存在。几个单连接完成这项工作。但是如何在单个MySQL查询中完成它。

使用PHP我选择所有" winterspecial"然后我用p1,p2 ...

构建查询

必须有更好的方法。请注意,属性必须是AND连接。 或者很简单,这将是一个简单的子选择。

INNER JOIN product_propeties p1 on p.pid = p1.pid AND product_propeties IN (
    SELECT * FROM property_groups WHERE "winterspecial"
)

2 个答案:

答案 0 :(得分:0)

这可能看起来有点笨拙,但目前我唯一能想出来的......

为了了解产品是否具有所有特殊属性,我们可以计算所有现有的特种属性和产品的特种属性,然后比较这两个数字。

然后我们可以从产品ID在找到的集合中的产品和product_properties中进行选择:

select ...
from products p
join product_properties pp on pp.pid = p.pid and pp.property in
  (select property from property_groups where group_name = 'winterspecial')
where p.pid in
(
  select pid
  from product_properties
  where property in 
    (select property from property_groups where group_name = 'winterspecial')
  group by pid
  having count(*) =
    (select count(*) from property_groups where group_name = 'winterspecial')
);

答案 1 :(得分:0)

啊,我想我现在得到了问题。对于给定的组,您似乎希望所有具有property_groups表中属性的产品。

这是一种方法。执行cross join以生成产品和属性列表。然后执行left join以匹配product_properties。通过聚合,您可以轻松判断所有所需属性是否与现有属性匹配:

select p.*
from products p cross join
     property_groups g left join
     product_properties pp 
     on pp.pid = p.id and pp.property = g.property
where g.group_name = 'winterspecial'
group by p.id
having count(distinct pp.property) = count(distinct g.property)

您实际上可以简单地将having子句改为其中一个:

having sum(pp.property is null) = 0           -- no null values
having count(pp.property) = count(g.property) -- all match

这些都应该是等价的。