返回所有相关WHERE匹配的行

时间:2015-10-24 18:51:02

标签: mysql select join many-to-many where

我需要返回一个与多对多关系中的所有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中。 任何帮助表示赞赏。

3 个答案:

答案 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