【问题标题】:Improve SQL query with multiple IN sub-query (filter by attribute system)使用多个 IN 子查询改进 SQL 查询(按属性系统过滤)
【发布时间】:2012-09-16 19:54:09
【问题描述】:

我有一个带有属性系统的产品目录。

我想创建一个允许客户按属性浏览产品的系统(例如在 Magento 上)。因此,我试图以编程方式检索具有特定值的属性(或具有许多特定值的许多属性)的产品列表(通过 ID 返回)。

效果很好,但是我的 SQL 查询很糟糕!

例如:如果我想检索具有这 3 个属性(和值)的产品列表,这是我当前的 SQL 查询:

  • 第一个过滤器:id_attribut = 3 AND value = 'Lorem ipsum'
  • 第二个过滤器:id_attribut = 4 AND value = 'Test2'
  • 第三个过滤器:id_attribut = 2 AND value = 'Bar2'

    选择 products.id
    来自产品
    加入 products_attributs ON products_attributs.id_product = products.id
    WHERE products_attributs.value = 'Lorem ipsum'
    AND products_attributs.id_attribut = 3
    AND products_attributs.id_product ==> 返回 ID:25、27
    在 (
        选择 id_product
        FROM products_attributes
        其中 id_attribut = 4
        AND 值 = 'Test2' ==> 返回 ID:27
        AND id_product IN (
            选择 id_product
            FROM products_attributes
            其中 id_attribut = 2
            AND 值 = 'Bar2' ==> 返回 ID:27
        )
    )

结果:返回 ID 27(这是与客户选择的三个属性对应的唯一产品)。

它运行良好,但不是很优雅,也不是很优化(想象一下,如果我有超过 10 个过滤器!)。

products_attributs 表:

---------------------------------------------- -- |编号 | id_product | id_attribute |价值 | ------------------------------------------------- | 1 | 25 | 1 |福 | | 2 | 25 | 2 |酒吧 | | 3 | 25 | 3 | Lorem ipsum | | 4 | 25 | 4 |测试 | | 5 | 27 | 1 | Foo2 | | 6 | 27 | 2 |酒吧2 | | 7 | 27 | 3 | Lorem ipsum | | 8 | 27 | 4 |测试2 | | 9 | 28 | 1 | ...等| --------------------------------------------------

我该如何改进?

非常感谢!

【问题讨论】:

    标签: mysql subquery database-performance


    【解决方案1】:

    拥有“好”SQL 的唯一方法是为所有属性创建列。这更难维护,所以我不推荐它。

    鉴于此,您可以多次加入您的属性表,如下所示:

    SELECT p.id
    FROM products p
    LEFT OUTER JOIN products_attributs pa1 ON pa1.id_product = p.id and pa1.value = 'Lorem ipsum' AND pa1.id_attribut = 3
    LEFT OUTER JOIN products_attributs pa2 ON pa2.id_product = p.id and pa2.value = 'Test2' AND pa1.id_attribut = 4
    LEFT OUTER JOIN products_attributs pa3 ON pa3.id_product = p.id and pa3.value = 'Bar2' AND pa1.id_attribut = 2
    

    祝你好运。

    【讨论】:

    • 它不适用于“LEFT OUTER JOIN”语句,但可以使用“JOIN”。非常感谢您的回答:您的 SQL 查询非常完美!
    • 如果您只使用 JOIN,它将需要所有三个属性的行。如果您描述它是如何“不起作用”的,也许有人可以提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-03-08
    • 2011-10-27
    • 2015-08-05
    • 1970-01-01
    • 2020-10-07
    • 2013-06-07
    • 2015-12-30
    • 2018-05-17
    相关资源
    最近更新 更多