MySQL:具有多个匹配项的JOIN和WHERE

时间:2019-03-26 22:26:11

标签: mysql sql join

我想使用以下查询从products表中选择具有ID 2和5的属性的产品:

SELECT `products`.`title`, `products`.`price` 
FROM `products` 
LEFT JOIN `products_attributes_mapping` 
    ON `products`.`id` = `products_attributes_mapping`.`product_id` 
WHERE 
    `products_attributes_mapping`.`attribute_value_id` IN (2) 
    AND `products_attributes_mapping`.`attribute_value_id` IN (5) 
GROUP BY `products`.`id`

我希望退货产品'Example product 1, blue, size 1'。但是,即使ID为1的产品在attribute_value_id表中分配了products_attributes_mapping 2和5,我也没有得到任何结果。

我使用IN是因为我希望能够提供多个属性,因此仅在示例中对其进行了简化。

SQL提琴:http://sqlfiddle.com/#!9/2fd94f2/1/0

模式

CREATE TABLE `products` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `title` varchar(255) CHARACTER SET utf8 NOT NULL,
    `price` double NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;

CREATE TABLE `products_attributes` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

CREATE TABLE `products_attributes_mapping` (
    `product_id` int(11) NOT NULL,
    `attribute_value_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `products_attributes_values` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `attribute_id` int(11) NOT NULL,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;

数据

INSERT INTO `products` VALUES 
    (1,'Example product 1, blue, size 1',10),
    (2,'Example product 2, yellow, size 1',10),
    (3,'Example product 3, black, size 2',15),
    (4,'Example product 4, red, size 2',15);

INSERT INTO `products_attributes` VALUES 
    (1,'Color'),
    (2,'Size');

INSERT INTO `products_attributes_mapping` VALUES 
    (1,2),
    (1,5),
    (2,4),
    (2,5),
    (3,3),
    (3,6),
    (4,1),
    (4,6);

INSERT INTO `products_attributes_values` VALUES 
    (1,1,'red'),
    (2,1,'blue'),
    (3,1,'black'),
    (4,1,'yellow'),
    (5,2,'1'),
    (6,2,'2'),
    (7,2,'3'),
    (8,2,'4');

1 个答案:

答案 0 :(得分:2)

使用聚合确实可以解决。您可以使用ArrayStoreException子句来确保产品具有某些属性值:

HAVING

your DB fiddle 中,此查询返回:

SELECT p.title, p.price
FROM products p
INNER JOIN products_attributes_mapping pm ON p.id = pm.product_id 
GROUP BY p.id, p.title, p.price
HAVING 
    MAX(pm.attribute_value_id = 2) = 1
    AND MAX(pm.attribute_value_id = 5) = 1

您可以通过添加更多title | price ---------------------------------|------- Example product 1, blue, size 1 | 10 条件来轻松扩展表达式。

另一种选择是使用一系列带有关联子查询的AND MAX(...) = 1条件来搜索属性表。同样好,但是如果您需要添加许多条件,它将扩展为更长的查询。

相关问题