【问题标题】:Join with where in condition difficulties加入条件困难的地方
【发布时间】:2013-05-31 15:40:09
【问题描述】:

我有product 表和product_attributes 表。我想要过滤具有必要属性的产品,这是我的 sql:

SELECT * FROM product p 
INNER JOIN product_attributes p2 ON p.id = p2.product_id
WHERE p2.attribute_id IN (637, 638, 629))

但是,即使产品只有一个属性(例如 637),它也会给我所有产品。但我需要具有所有给定属性(637、638、629)的产品。

【问题讨论】:

  • 显示一些示例数据和预期结果将有助于我们为您提供帮助。
  • 你显式地实现了 WHERE 子句来检查表 p2 中的出现。所以你甚至不会试图限制在决赛桌。您需要一个外部 SELECT 并过滤派生表。

标签: mysql sql join filter


【解决方案1】:

有一个相当标准的方法:

select * from product
where id in (
    SELECT id
    FROM product p 
    JOIN product_attributes p2 ON p.id = p2.product_id
      AND p2.attribute_id IN (637, 638, 629)
    GROUP BY id
    HAVING COUNT(distinct attribute_id) = 3) 

HAVING 子句确保有 3 个不同的属性 ID(即它们都被找到了)。

这可以表示为直接连接(而不是 ID IN(...)),但它更易于阅读并且应该像这样执行。

稍微感兴趣的可能是将属性 id 条件移动到 JOIN 的 ON 条件中。

【讨论】:

  • 谢谢@Bohemian,请在上面的答案中查看我的评论
  • 有什么理由使用AND p2.attribute_id 而不是WHERE p2.attribute_id 吗?
  • 优化的通常将它们解释为相同,但完成的数据库不会。一般来说,将其置于连接条件中会表现得更好(至少不会更差)。
【解决方案2】:

这是“set-within-sets”子查询的示例。我喜欢通过聚合和having 子句来解决这些问题,因为这是最灵活的解决方案:

SELECT p.*
FROM product p join
     product_attributes pa
     on p.id = pa.product_id
group by p.id
having sum(pa.attribute_id = 637) > 0 and
       sum(pa.attribute_id = 638) > 0 and
       sum(pa.attribute_id = 629) > 0

另一种having 子句是:

having count(distinct case when pa.attribute_id IN (637, 638, 629)
                           then pa.attribute_id
                      end) = 3

【讨论】:

    【解决方案3】:

    您可以使用这样的查询:

    SELECT * FROM product p 
    INNER JOIN product_attributes p21 
            ON p.id = p21.product_id and p21.attribute_id = 637
    INNER JOIN product_attributes p22 
            ON p.id = p22.product_id and p22.attribute_id = 638
    INNER JOIN product_attributes p23 
            ON p.id = p23.product_id and p23.attribute_id = 629
    

    【讨论】:

    • 我认为这是不好的方法,如果用户想过滤 50 个属性怎么办? :)
    • 在这种情况下,您应该使用来自其他答案的查询 :)
    猜你喜欢
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 2017-03-19
    相关资源
    最近更新 更多