MySQL:JOIN 和 WHERE 有多个匹配项

标签 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 的产品在 products_attributes_mapping 表中分配了 attribute_value_id 2 和 5。

我使用 IN 因为我希望能够提供多个属性,所以我简化了它只是为了示例。

SQL fiddle :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');

最佳答案

使用聚合确实是一种解决方案。您可以使用 HAVING 子句来确保产品具有某些属性值:

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

your DB fiddle ,此查询返回:

title                            | price
---------------------------------|-------
Example product 1, blue, size 1  | 10

您可以通过添加更多 AND MAX(...) = 1 条件轻松扩展表达式。

另一种选择是使用一系列具有相关子查询的WHERE EXISTS 条件来搜索属性表。这同样好,但如果您需要添加许多条件,则会扩展为更长的查询。

关于MySQL:JOIN 和 WHERE 有多个匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55367045/

相关文章:

mysql - SQL 如何将: from two tables that has 2 same data in other named columns,其中一个需要统计

sql - 如何解决选择框中的 N + 1 问题?

mysql - 在字符串中查找表的数据

mysql - 如何在 MYSQL 服务器中使用单个 JOIN 语句更新两个表?

mysql - 如何比较行之间的值并找到响应的平均值?

sql - 从 SQL/关系代数类比到 *nix 命令行过滤器/工具

php - 调用存储过程后从 php 访问 LAST_INSERT_ID()

MYSQL 对同一表的附加选择

mysql文件导入多行字符串

php - 索引列但保持快速插入