【问题标题】:MySQL Select - join tables that match allMySQL Select - 连接所有匹配的表
【发布时间】:2023-03-27 10:24:01
【问题描述】:

我有一个包含 3 个表的数据库 - 产品、标签和产品标签。我需要一个查询 返回具有所有指定标签的所有产品。换句话说,不要返回 如果产品没有所有指定的标签。

products
+----+-----+--------+------------------------+
| id | uid | name   | description            |
+----+-----+--------+------------------------+
| 1  | p1  | ball   | something that bounces |
+----+-----+--------+------------------------+
| 2  | p2  | block  | for building stuff     |
+----+-----+--------+------------------------+
| 3  | p3  | bucket | holds stuff            |
+----+-----+--------+------------------------+
| 4  | p4  | shovel | scoops stuff           |
+----+-----+--------+------------------------+


tags
+----+-----+--------+
| id | uid | name   |
+----+-----+--------+
| 1  | t1  | blue   |
+----+-----+--------+
| 2  | t2  | red    |
+----+-----+--------+
| 3  | t3  | green  |
+----+-----+--------+
| 4  | t4  | yellow |
+----+-----+--------+
| 5  | t5  | orange |
+----+-----+--------+


product_tags
+-------------+---------+
| product_uid | tag_uid |
+-------------+---------+
| p1          | t1      |
+-------------+---------+
| p1          | t2      |
+-------------+---------+
| p2          | t3      |
+-------------+---------+
| p2          | t4      |
+-------------+---------+
| p2          | t5      |
+-------------+---------+
| p3          | t1      |
+-------------+---------+
| p4          | t1      |
+-------------+---------+
| p4          | t5      |
+-------------+---------+

以下是我正在寻找的一些结果示例:

选择红色(t2)的产品:

+-------------+------+
| product_uid | name |
+-------------+------+
| p1          | ball |
+-------------+------+

选择所有红色和蓝色的产品(t2,t1):

+-------------+------+
| product_uid | name |
+-------------+------+
| p1          | ball |
+-------------+------+

选择所有红色、蓝色和黄色(t2、t1、t4)的产品:

+--------------------+
|     NO PRODUCTS    |
+--------------------+

选择所有蓝色 (t1) 的产品:

+-------------+--------+
| product_uid | name   |
+-------------+--------+
| p1          | ball   |
+-------------+--------+
| p3          | bucket |
+-------------+--------+
| p4          | shovel |
+-------------+--------+

选择所有蓝色和橙色的产品(t1,t5):

+-------------+--------+
| product_uid | name   |
+-------------+--------+
| p4          | shovel |
+-------------+--------+

这里是一个已经设置好的 SQLFiddle 的链接。我尝试了 LEFT JOIN,但它没有得到我想要的东西。

http://sqlfiddle.com/#!9/795615/6

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    编辑:更新 @spencer7593 的建议

    假设您的标签是唯一的,您可以使用 count 仅按匹配次数等于传递的标签的产品进行过滤。

    这种方法的优点是允许无限的标签作为输入。

    SELECT products.uid
    FROM product_tags
    JOIN products ON product_tags.product_uid = products.uid
    WHERE product_tags.tag_uid IN ('t2', 't1')
    GROUP BY products.uid
    HAVING COUNT(DISTINCT product_tags.tag_uid) = 2
    

    或者对于 3 个标签:

    SELECT products.uid
    FROM product_tags
    JOIN products ON product_tags.product_uid = products.uid
    WHERE product_tags.tag_uid IN ('t3', 't2', 't1')
    GROUP BY products.uid
    HAVING COUNT(DISTINCT product_tags.tag_uid) = 3
    

    等等……

    【讨论】:

    • 这可以在没有外部查询的情况下实现。将 SELECT 列表中的 COUNT() 聚合移动到 HAVING 子句中的条件中... ... GROUP BY products.uid HAVING COUNT(DISTINCT product_tags.tag_uid) = 3
    • 确实!好决定。我总是忘记拥有。更新了原来的答案
    【解决方案2】:

    试试这个:

    select product_id,tag_uuid,uid,d.name,description,color from
    (
    
    select product_id,tag_uuid,b.name as color from
    (select product_id,tag_uuid from product_tags) as a
    LEFT JOIN
    (select uid,name from tags) as b
    on a.tag_uuid = b.uid
    
    ) as c
    left JOIN
    (select id,uid,name,description from products) as d
    on c.product_id = d.uid
    
    
    where color = 'blue'
    

    如果您需要其他颜色,只需更改位置即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2019-05-15
      • 1970-01-01
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      • 2021-12-23
      相关资源
      最近更新 更多