MySQL select join where AND where

13

我在我的数据库中有两个表:

Products

  • id(int,主键)
  • name(varchar)

ProductTags

  • product_id(int)
  • tag_id(int)

我想选择所有包含给定标签的产品。我试过了:

SELECT
    *
FROM
    Products
JOIN ProductTags ON Products.id = ProductTags.product_id
WHERE
    ProductTags.tag_id IN (1, 2, 3)
GROUP BY
    Products.id

但它给我返回了拥有任何一个给定标签的产品,而不是同时拥有所有给定标签的产品。写 WHERE tag_id = 1 AND tag_id = 2 是无意义的,因为不会返回任何行。


1
我不明白你想要什么?你能否提供一些数据和例子来详细说明吗? - diagonalbatman
3个回答

22

这种问题被称为关系除法(relational division)

SELECT Products.* 
FROM Products
JOIN ProductTags ON Products.id = ProductTags.product_id
WHERE ProductTags.tag_id IN (1,2,3)
GROUP BY Products.id /*<--This is OK in MySQL other RDBMSs 
                          would want the whole SELECT list*/

HAVING COUNT(DISTINCT ProductTags.tag_id) = 3 /*Assuming that there is a unique
                                              constraint on product_id,tag_id you 
                                              don't need the DISTINCT*/

这解决了问题。我想知道最后一行的数字3代表什么。我使用以下代码可以得到正确的结果:HAVING COUNT(DISTINCT ProductTags.tag_id) = 1,并且可以使用任何大小的标签ID数组:WHERE ProductTags.tag_id IN (1,2,3,4) - Darrarski
1
您需要根据情况调整数字3。对于(1,2,3,4),您需要使用HAVING COUNT(DISTINCT ProductTags.tag_id) = 4,否则将会返回那些在这4个标签中有任意3个匹配标签的结果。 - Martin Smith

0

你需要使用 group by / count 来确保所有内容都被计算在内。

select Products.*
  from Products 
         join ( SELECT Product_ID
                  FROM ProductTags
                  where ProductTags.tag_id IN (1,2,3)
                  GROUP BY Products.id
                  having count( distinct tag_id ) = 3 ) PreQuery
        on ON Products.id = PreQuery.product_id 

0
MySQL中的WHERE fieldname IN (1,2,3)本质上是WHERE fieldname = 1 OR fieldname = 2 OR fieldname = 3的简写形式。因此,如果您使用WHERE ... IN时没有得到所需的功能,请尝试切换到OR。如果仍然无法获得所需的结果,则可能WHERE ... IN不是您需要使用的函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接