使用多个IN子查询改进SQL查询(按属性系统过滤)

时间:2012-09-16 19:54:09

标签: mysql subquery database-performance

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

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

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

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

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

    SELECT products.id
    FROM products
    JOIN 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            ==> return ID: 25, 27
    IN (
        SELECT id_product
        FROM products_attributs
        WHERE id_attribut = 4
        AND value = 'Test2'                  ==> return ID: 27
        AND id_product IN (
            SELECT id_product
            FROM products_attributs
            WHERE id_attribut = 2
            AND value = 'Bar2'           ==> return ID: 27
        )
    )

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

它效果很好,但它不优雅而且不是很优化(想象一下,如果我有10个以上的过滤器!)。

products_attributs表:

-------------------------------------------------
| id | id_product | id_attribut | value         |
-------------------------------------------------
| 1  | 25         | 1           | Foo           |
| 2  | 25         | 2           | Bar           |
| 3  | 25         | 3           | Lorem ipsum   |
| 4  | 25         | 4           | Test          |
| 5  | 27         | 1           | Foo2          |
| 6  | 27         | 2           | Bar2          |
| 7  | 27         | 3           | Lorem ipsum   |
| 8  | 27         | 4           | Test2         |
| 9  | 28         | 1           | ... etc       |
-------------------------------------------------

我该如何改进?

非常感谢!

1 个答案:

答案 0 :(得分:1)

唯一的方法是拥有" nice" 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
祝你好运。