从上一个WHERE条件获取结果

时间:2019-07-31 09:42:10

标签: mysql sql

我有以下数据库设计。

产品

+----+----------------------------------+
| id | name                             |
+----+----------------------------------+
| 1  | Product 1, Intel, Celeron, N3350 |
| 2  | Product 2, Intel, Celeron, N3350 |
| 3  | Product 3, Intel, i5, 8250U      |
| 4  | Product 4, Intel, i9, 8950HK     |
| 5  | Product 5, Intel, i9, 8950HK     |
+----+----------------------------------+

属性

+----+--------------+
| id | name         |
+----+--------------+
| 11 | Manufacturer |
| 22 | Type         |
| 33 | Model        |
+----+--------------+

ATTRIBUTE_VALUES

+-----+---------+
| id  | value   |
+-----+---------+
| 111 | Intel   |
| 222 | Celeron |
| 333 | i5      |
| 444 | i9      |
| 555 | N3350   |
| 666 | 8250U   |
| 777 | 8950HK  |
+-----+---------+

最后,链接所有这些表的表:

PRODUCT_ATTRIBUTES_VALUES

+------------+--------------+--------------------+
| product_id | attribute_id | attribute_value_id |
+------------+--------------+--------------------+
| 1          | 11           | 111                |
| 1          | 22           | 222                |
| 1          | 33           | 555                |
| 2          | 11           | 111                |
| 2          | 22           | 222                |
| 2          | 33           | 555                |
| 3          | 11           | 111                |
| 3          | 22           | 333                |
| 3          | 33           | 666                |
| 4          | 11           | 111                |
| 4          | 22           | 444                |
| 4          | 33           | 777                |
| 5          | 11           | 111                |
| 5          | 22           | 444                |
| 5          | 33           | 777                |
+------------+--------------+--------------------+

所有这些都是关于过滤器产品的。

我想返回每个属性过滤器的结果。

如果我过滤依据:

  • 属性'Intel'=>它应返回所有5个结果。
  • 键入'Celeron'=>它应返回2个结果(仅Celeron)

SQL-FIDDLE

 SELECT products.id, products.name FROM `products` LEFT JOIN
 `product_attributes_values` ON
 `product_attributes_values`.`product_id`=`products`.`id` LEFT JOIN
 `attributes` ON
 `attributes`.`id`=`product_attributes_values`.`attribute_id` LEFT JOIN
 `attribute_values` ON
 `attribute_values`.`id`=`product_attributes_values`.`attribute_value_id`
 WHERE ((attributes.id = 11 AND `attribute_values`.`id` IN (111)) OR 
 (`attributes`.`id` = 22 AND `attribute_values`.`id` IN (222)) ) GROUP
 BY `products`.`id` LIMIT 10

2 个答案:

答案 0 :(得分:3)

尝试这个

SELECT
    products.id,
    products.name
FROM
    `products`
    LEFT JOIN `product_attributes_values`
        ON `product_attributes_values`.`product_id`=`products`.`id`
    LEFT JOIN `attributes`
        ON `attributes`.`id`=`product_attributes_values`.`attribute_id`
    LEFT JOIN `attribute_values`
        ON `attribute_values`.`id`=`product_attributes_values`.`attribute_value_id`
WHERE
    attributes.id = 11
    OR attributes.id = 22
GROUP BY
    products.id,
    products.name
HAVING
    MAX(CASE WHEN attributes.id = 11 THEN attribute_values.id ELSE NULL END) IN (111)
    AND MAX(CASE WHEN attributes.id = 22 THEN attribute_values.id ELSE NULL END) IN (222)
LIMIT
    10

如果您知道所有ID,则不需要所有这些联接

SELECT
    p.id,
    p.name
FROM
    `products` as p
    LEFT JOIN `product_attributes_values` as pav1
        ON  p.id = pav1.product_id
            and pav1.attribute_id = 11
    LEFT JOIN `product_attributes_values` as pav2
        ON  p.id = pav2.product_id
            and pav2.attribute_id = 22
WHERE
    pav1.attribute_value_id = 111
    AND pav2.attribute_value_id = 222

答案 1 :(得分:2)

这是一个关系划分问题,这是一个解决方案:

SELECT products.id, products.name
FROM products
WHERE EXISTS (
  SELECT 1
  FROM product_attributes_values
  INNER JOIN attributes ON product_attributes_values.attribute_id = attributes.id
  INNER JOIN attribute_values ON product_attributes_values.attribute_value_id = attribute_values.id 
  WHERE product_attributes_values.product_id = products.id AND (
    (attributes.attribute_name = 'Manufacturer' AND attribute_values.value = 'Intel®') OR
    (attributes.attribute_name = 'Type'         AND attribute_values.value = 'Celeron®')
  )
  HAVING COUNT(*) = 2 -- this must match the number of conditions
)