【问题标题】:MySQL Join QuestionMySQL 加入问题
【发布时间】:2010-04-26 21:18:19
【问题描述】:

您好,我正在努力编写特定的 MySQL 连接查询。

我有一个包含产品数据的表,每个产品可以属于多个类别。使用链接表可以满足这种 m:m 关系。

对于这个特定的查询,我希望检索属于给定类别的所有产品,但对于每个产品记录,我还想返回产品所属的其他类别。

理想情况下,我希望在类别表上使用内部联接来实现这一点,而不是为每个产品记录执行额外的查询,这将是非常低效的。

我的简化架构大致设计如下:

产品表:

product_id, name, title, description, is_active, date_added, publish_date, etc....

分类表:

category_id, name, title, description, etc...

product_category 表:

product_id, category_id

我编写了以下查询,它允许我检索属于指定 category_id 的所有产品。但是,我真的很难弄清楚如何检索产品所属的其他类别。

SELECT p.product_id, p.name, p.title, p.description
FROM prod_products AS p
LEFT JOIN prod_product_category AS pc
ON pc.product_id =  p.product_id
WHERE pc.category_id = $category_id
AND UNIX_TIMESTAMP(p.publish_date) < UNIX_TIMESTAMP()
AND p.is_active = 1
ORDER BY p.name ASC

我很乐意检索与每个返回的产品行相关的类别 ID,因为我会将所有类别数据存储在一个对象中,而我的应用程序代码可以处理其余部分。

非常感谢,

理查德

【问题讨论】:

    标签: mysql left-join inner-join


    【解决方案1】:
    SELECT p.product_id, p.name, p.title, p.description, 
      GROUP_CONCAT(otherc.category_id) AS other_categories
    FROM prod_products AS p
    JOIN prod_product_category AS pc
      ON pc.product_id =  p.product_id
    LEFT JOIN prod_product_category AS otherc
      ON otherc.product_id = p.product_id AND otherc.category_id != pc.category_id
    WHERE pc.category_id = $category_id
      AND UNIX_TIMESTAMP(p.publish_date) < UNIX_TIMESTAMP()
      AND p.is_active = 1
    GROUP BY p.product_id
    ORDER BY p.name ASC
    

    【讨论】:

    • 太棒了,非常感谢。我从没想过第二次在那个表上执行连接,以及使用 not 运算符。
    【解决方案2】:

    您将使用对 product_category 表的内连接,在那里进行左连接是没有意义的,因为您在条件中使用它的值。然后对 product_category 表进行左连接以获取其他类别,并加入数据的类别:

    select
      p.product_id, p.name, p.title, p.description,
      c.category_id, c.name, c.title
    from
      prod_products p
      inner join prod_product_category pc on pc.product_id = p.product_id
      left join prod_product_category pc2 on pc2.product_id = p.product_id
      left join prod_categories c on c.category_id = pc2.category_id
    where
      pc.category_id = @category_id and
      unix_timestamp(p.publish_date) < unix_timestamp() and
      p.is_active = 1
    order by
      p.name
    

    【讨论】:

      猜你喜欢
      • 2011-04-03
      • 2011-10-14
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多