简体   繁体   中英

Improve SQL query with multiple IN sub-query (filter by attribute system)

I have a product catalog with a attribute system.

I want to create a system that will allow client to browse products by attribute (like on Magento). So, I am trying to programatically retrieve a list of products (by ID return) that have a attribute with a specific value (or many attributes with many specific values).

It works well, but my SQL query is horrible!

For exemple: if I want to retrieve a list of products that have these 3 attributes (and values), here's my current SQL query:

  • 1st filter: id_attribut = 3 AND value = 'Lorem ipsum'
  • 2nd filter: id_attribut = 4 AND value = 'Test2'
  • 3rd filter: id_attribut = 2 AND value = 'Bar2'

     SELECT products.id \nFROM products \nJOIN products_attributs ON products_attributs.id_product = products.id \nWHERE products_attributs.value = 'Lorem ipsum' \nAND products_attributs.id_attribut = 3 \nAND products_attributs.id_product ==> return ID: 25, 27 \nIN ( \n    SELECT id_product \n    FROM products_attributs \n    WHERE id_attribut = 4 \n    AND value = 'Test2' ==> return ID: 27 \n    AND id_product IN ( \n        SELECT id_product \n        FROM products_attributs \n        WHERE id_attribut = 2 \n        AND value = 'Bar2' ==> return ID: 27 \n    ) \n)  

Result: return ID 27 (this is the only product that corresponds to the three attributes selected by the customer).

It works well but it's not elegant and not very optimised (imagine if I have more than 10 filters !).

The products_attributs table:

-------------------------------------------------
| 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       |
-------------------------------------------------

How can I improve that?

Thank a lot!

The only way to have "nice" SQL is to make columns for all of your attributes. That's much harder to maintain, so I wouldn't recommend it.

Given than, you can join back to your attributes table multiple times, like this:

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

Good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM