MySQL获得具有

时间:2016-02-16 15:45:04

标签: mysql

我遇到了从数据库中提取记录的问题。我有产品和产品有属性。有一个数据透视表,用于将product_properties连接到产品。产品可以具有多种属性。

现在我的数据库结构:

产品

| id | title            |
-------------------------
| 1  | Mercedes A green |
| 2  | Volvo V40 green  |
| 3  | Audi A3 green    |

PROPERTY_VALUE

| id | property_id | value    |
-------------------------------
| 1  |           1 | Volvo    |
| 2  |           1 | Mercedes |
| 3  |           2 | Green    |
| 4  |           1 | Audi     |

product_property

| product_id | property_id | property_value_id | no column, just info
------------------------------------------------
|          1 |           1 |                 2 | Mercedes
|          1 |           2 |                 3 | Green
|          2 |           1 |                 1 | Volvo
|          2 |           2 |                 3 | Green
|          3 |           1 |                 4 | Audi
|          3 |           2 |                 3 | Green

现在我希望得到所有梅赛德斯或沃尔沃的产品,绿色。我希望product.id 1& 2将被退回。

所以我在考虑这样的事情:

SELECT product.*
FROM product
  JOIN product_property ON product.id = product_property.product_id
WHERE
   product_property.property_value_id IN (1, 2, 3)
GROUP BY product.id;

但这当然会让我回报所有产品1,2和3。

所以我需要做这样的事情:

SELECT product.*
FROM product
  JOIN product_property ON product.id = product_property.product_id
WHERE
   (product_property.property_id = 1 AND product_property.property_value_id IN (1, 2))
   AND
   (product_property.property_id = 2 AND product_property.property_value_id IN (3))
GROUP BY product.id;

但这没有任何回报。

我想我已经接近了,但我无法弄清楚这个查询的最后一步。谁知道......

2 个答案:

答案 0 :(得分:1)

您只需添加HAVING子句:

SELECT product.id, product.title
FROM product
  JOIN product_property ON product.id = product_property.product_id
WHERE
   product_property.property_value_id IN (1, 2, 3)
GROUP BY product.id, product.title
HAVING COUNT(CASE WHEN property_value_id IN (1,2) THEN 1 END) > 0 AND
       COUNT(CASE WHEN property_value_id IN (3) THEN 1 END) > 0

HAVING子句使用条件聚合来检查与至少一个 property_value_id 1或2 相关的产品和property_value_id=3相关。

Demo here

答案 1 :(得分:0)

你也可以做这样的事情 - 可能比Giorgios的答案慢一点(我怀疑它本身比仅仅运行几个LEFT JOIN慢一点)......

SELECT p.*
  FROM product_property x 
  JOIN property_value y 
    ON y.property_id = x.property_id 
   AND x.property_value_id = y.id 
  JOIN product p
    ON p.id = x.product_id
 GROUP 
    BY product_id
HAVING MAX(CASE WHEN x.property_id = 1 THEN y.value END) IN ('Volvo','Mercedes')
   AND MAX(CASE WHEN x.property_id = 2 THEN y.value END) IN ('Green');