MySQL产品/类别/目录加入

时间:2015-06-30 05:55:02

标签: mysql

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

每个目录中都有多个类别,每个类别中都有多个产品。属于同一目录的类别应该具有完全相同的产品,但遗憾的是它们在某些情况下并不存在。

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

因此,我需要解决的结果是缺少并需要添加的product_id / category_id对列表。

我如何在MySQL中实现这一目标?

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

任何MySQL专家愿意帮忙吗?

更新:

根据请求,这里是create table 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。

2 个答案:

答案 0 :(得分: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_idcategory_id catalog_id的完整列表。

您现在要做的就是从表中找到丢失的product_idcategory_id对。您可以在初始查询中使用LEFT JOIN来完成此操作。

答案 1 :(得分:0)

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

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)