【问题标题】:MySQL Product/Category/Catalog JoinMySQL 产品/类别/目录加入
【发布时间】:2015-09-16 19:07:02
【问题描述】:

我有一个现有的填充 MySQL 表,其中包含三列:product_id、category_id 和 catalog_id

每个目录中都有多个类别,每个类别中都有多个产品。属于同一目录的类别应该包含完全相同的产品,但不幸的是在某些情况下它们没有。

我需要找出每个类别中缺少的产品。缺失意味着产品存在于至少一个属于同一目录但不存在于该特定类别中的其他类别中。

所以我需要从中得到的结果是缺少并需要添加的 product_id/category_id 对列表。

如何在 MySQL 中实现这一点?

我尝试创建一个由不同的 product_id 和 catalog_id 对填充的表,以获取每个目录的所有产品,然后将其与主表连接,但我不确定要执行哪种类型的连接。

有愿意提供帮助的 MySQL 专家吗?

更新:

根据一个请求,这里是创建表的SQL(这是实际场景的简化版):

create table product (
  product_id bigint not null,
  category_id bigint not null,
  catalog_id bigint not null
);

更新 2:

澄清:属于同一目录的每个类别必须与属于同一目录的所有其他类别具有完全相同的产品。如果产品属于一个类别而不属于属于同一目录的另一个类别,则该产品缺失,需要将其标识为 product_id/category_id 对。

更新 3:

根据另一个请求,这里是示例数据:

insert into product (product_id, category_id, catalog_id) values (1, 1, 1);
insert into product (product_id, category_id, catalog_id) values (2, 1, 1);
insert into product (product_id, category_id, catalog_id) values (3, 1, 1);
insert into product (product_id, category_id, catalog_id) values (1, 2, 1);
insert into product (product_id, category_id, catalog_id) values (3, 2, 1);

在这种情况下,product_id 2 和 category_id 2 对将被标识为结果的一部分。这是因为类别 1 和类别 2 属于同一个目录 (1),类别 2 缺少产品,即 product_id 2。

【问题讨论】:

  • 我想我错过了你的 sqlFiddle?
  • @TimBiegeleisen 架构只有这三列都是 bigint 类型。
  • SO上有SQL问题,一张图真的值一千字。如果您有一些显示问题的示例数据,我们会更容易消化。
  • @GuyT:不确定 sqlFiddle 在这种特定情况下会如何提供帮助。这个要求很容易理解,但从公认的答案来看,解决起来要困难得多。
  • @GuyT:不用担心 :) 我脾气暴躁,因为这几乎是我睡觉的时间(加利福尼亚的午夜)。看起来您在 Georgos 的答案提供的演示中也获得了 sqlFiddle。这一定是你的幸运日!

标签: mysql


【解决方案1】:

您也可以通过优化方式来做到这一点-

Hitesh> select * from product;                                                                                                        +------------+-------------+------------+
| product_id | category_id | catalog_id |
+------------+-------------+------------+
|          1 |           1 |          1 |
|          2 |           1 |          1 |
|          3 |           1 |          1 |
|          1 |           2 |          1 |
|          3 |           2 |          1 |
|          4 |           2 |          1 |
|          5 |           2 |          1 |
|          1 |           2 |          2 |
|          2 |           1 |          2 |
+------------+-------------+------------+
9 rows in set (0.00 sec)

Hitesh>
    SELECT product_id, category_id, catalog_id
    FROM
      (SELECT DISTINCT p1.product_id, p2.category_id, p1.catalog_id
       FROM product p1 JOIN product p2 ON p1.catalog_id=p2.catalog_id) tmp
    WHERE NOT EXISTS (SELECT 1 FROM product 
                      WHERE category_id = tmp.category_id AND   
                            product_id=tmp.product_id AND   
                            catalog_id=tmp.catalog_id);
+------------+-------------+------------+
| product_id | category_id | catalog_id |
+------------+-------------+------------+
|          4 |           1 |          1 |
|          5 |           1 |          1 |
|          2 |           2 |          1 |
|          2 |           2 |          2 |
|          1 |           1 |          2 |
+------------+-------------+------------+
5 rows in set (0.00 sec)

【讨论】:

    【解决方案2】:

    您可以使用以下查询来完成:

    SELECT s1.product_id, s1.category_id
    FROM (
      SELECT t1.product_id, t2.category_id, t1.catalog_id
      FROM (
        SELECT DISTINCT product_id, catalog_id
        FROM product) AS t1
      CROSS JOIN (
        SELECT DISTINCT category_id, catalog_id
        FROM product) AS t2
      WHERE t1.catalog_id = t2.catalog_id ) AS s1
    LEFT JOIN product AS s2 
    ON s1.catalog_id = s2.catalog_id AND 
       s1.category_id = s2.category_id AND
       s1.product_id = s2.product_id
    WHERE s2.product_id IS NULL
    

    Demo here

    说明:

    这个查询:

    SELECT DISTINCT product_id, catalog_id
    FROM product
    

    为您提供每个目录中所有不同产品的列表:

    product_id  catalog_id
    -----------------------
    1           1
    2           1
    3           1
    

    如果您对每个目录的所有不同类别执行上述CROSS JOIN:

    SELECT t1.product_id, t2.category_id, t2.catalog_id
    FROM (
      SELECT DISTINCT product_id, catalog_id
      FROM product) AS t1
    CROSS JOIN (
      SELECT DISTINCT category_id, catalog_id
      FROM product) AS t2
    WHERE t1.catalog_id = t2.catalog_id  
    

    你得到:

    product_id  category_id catalog_id
    ----------------------------------
    1           1           1 
    1           2           1
    2           1           1
    2           2           1
    3           1           1
    3           2           1
    

    以上是包含product_id 和category_id 和catalog_id 的完整列表。

    您现在要做的就是从您的表中找到缺少的product_id、category_id 对。您可以在初始查询中使用LEFT JOIN 来做到这一点。

    【讨论】:

    • 谢谢!我还没有尝试过,但乍一看它看起来是正确的。我只是没有意识到我偶然发现了一个看起来要复杂得多的问题:)
    • 我从来没有更新过这个。您的回答极大地帮助了我编写最终的生产代码。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 2015-04-22
    相关资源
    最近更新 更多