【问题标题】:MySQL several inner joins vs subqueryMySQL几个内部连接与子查询
【发布时间】:2016-01-04 12:30:13
【问题描述】:

在无需使用 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

我想用“winterspecial”加入“property_groups”表,上面的例子我不知道怎么做。问题是每个属性都需要存在。几个单连接可以完成这项工作。但是如何在单个 MySQL 查询中做到这一点。

使用 PHP,我选择所有“winterspecial”,然后使用 p1、p2 构建查询...

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

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

【问题讨论】:

  • 我不明白。您想展示具有所有属性的产品吗?而不是 'toy', 'green', '15"', 'broken' 你想选择 'toy', 'color=green', 'size=15"', 'state=broken'?或者还有什么?请显示所需的输出。
  • 请记住,子查询和连接是相同的东西,既不慢也不快。
  • @Mjh 。 . .它们在功能上是等效的,但不一定以相同的方式实现。操作。 . .请编辑问题并提供示例数据和所需结果。一个完整的查询也可能传达你想要做什么。
  • @GordonLinoff - 我评论的前提是,如果使用子查询编写查询,也可以使用 JOIN 编写查询。现在,至于哪个更快,实际的实现细节在这一点上是无关紧要的。如果可以通过子查询来实现正确的解决方案,那么也可以通过 JOIN 来实现。

标签: php mysql join subquery


【解决方案1】:

这可能看起来有点笨拙,但这是我目前唯一能想到的……

为了知道一个产品是否具有所有的winterspecial属性,我们可以统计所有现有的winterspecial属性和产品的winterspecial属性,然后比较这两个数字。

然后我们可以从products和product_properties中选择product ID在搜索结果中的位置:

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')
);

【讨论】:

    【解决方案2】:

    啊,我想我现在明白了。对于给定的组,您似乎想要所有具有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
    

    这些都应该是等价的。

    【讨论】:

      猜你喜欢
      • 2015-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2013-04-26
      • 1970-01-01
      相关资源
      最近更新 更多