我需要返回一个与多对多关系中的所有WHERE语句匹配的结果。解释:
我有这样的表结构。
Wink3319:Camelot1
f.signat@cnb.fr:arondep60
Wildthing83:A1106P
fr:arondep60
现在我有这样的情况:
CREATE TABLE `product` (
`product_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`product_id`));
CREATE TABLE `product_has_tag` (
`product_id` INT UNSIGNED NOT NULL,
`tag_id` INT UNSIGNED NOT NULL
);
CREATE TABLE `tag` (
`tag_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`value` VARCHAR(30) NULL,
PRIMARY KEY (`tag_id`));
基本上,有一种产品同时具有标签和其余部分。现在我需要一个SQL搜索条件,它只返回与两个标签相关联的产品。像
这样的东西Product: {
[product_id:1],
[product_id:2],
[product_id:3]};
Tags: {
[tag_id:1, value:'XX'],
[tag_id:2, value:'YY']}
ProductHasTag: {
[product_id:1, tag_id:1],
[product_id:1, tag_id:2],
[product_id:2, tag_id:1],
[product_id:3, tag_id:2]}
显然不起作用,因为搜索值不是在一个标签中,而是在TWO中。 任何帮助表示赞赏。
答案 0 :(得分:1)
您需要处理两个不同的标记,就像它们是两个不同的列一样。这需要一些花哨的加入工作。
此查询可让您的产品符合您的第一个标准。
SELECT p.*, t1.value tag1
FROM product p
JOIN product_has_tag pt1 ON p.product_id = pt1.product_id
JOIN tag t1 ON pt1.tag_id = t1.tag_id AND t1.value LIKE '%X%'
您可以在此查询中添加一些内容,以获取所需的两个标记。
SELECT p.*, t1.value tag1, t2.value tag2
FROM product p
JOIN product_has_tag pt1 ON p.product_id = pt1.product_id
JOIN tag t1 ON pt1.tag_id = t1.tag_id AND t1.value LIKE '%X%'
JOIN product_has_tag pt2 ON p.product_id = pt2.product_id
JOIN tag t2 ON pt2.tag_id = t2.tag_id AND t2.value LIKE '%Y%'
JOIN项将导致此查询将产品行与两个匹配的标记隔离。
此查询中的value LIKE '%match%'
模式会导致性能下降。如果您可以使用value LIKE 'match%'
或value = 'match'
,则可以使用value
列上的索引。
答案 1 :(得分:1)
您只需将WHERE
更改为HAVING
并使用SUM CASE WHEN
SELECT `product`.`product_id` -- *
FROM `product`
LEFT JOIN product_has_tag
USING(product_id)
LEFT JOIN tag
USING(tag_id)
GROUP BY `product`.`product_id`
HAVING SUM(CASE WHEN `value` LIKE '%X%' THEN 1 END) > 0
AND SUM(CASE WHEN `value` LIKE '%Y%' THEN 1 END) > 0
的 SqlFiddleDemo
强>
答案 2 :(得分:0)
您可以总结匹配的代码,只返回2个匹配的结果。
SELECT * FROM product
LEFT JOIN product_has_tag USING(product_id)
LEFT JOIN tag USING(tag_id)
WHERE value LIKE '%X%' OR value LIKE '%Y%'
GROUP BY product_id HAVING COUNT(DISTINCT tag_id) = 2