mysql为具有重复值的某些单元格的行选择简单连接

时间:2014-02-18 20:37:20

标签: mysql sql join

我正在尝试使用两个表执行MySQL SELECT,只有当有多个行且其中两列具有重复值时,才会显示每个表中的列。

以下SELECT语句为客户提供的所有订单提供customer_id,order_id,product_ids和skus ......

select orders2.customer_id, items2.order_id, items2.product_id, items2.sku 
from orders orders2, order_items items2
where orders2.status = 'complete' 
    and orders2.customer_id is not null
    and orders2.entity_id = items2.order_id
order by orders2.customer_id ASC, items2.product_id ASC;

给我结果...

+-------------+----------+------------+--------------------------+
| customer_id | order_id | product_id | sku                      |
+-------------+----------+------------+--------------------------+
|       29813 |    38025 |        306 | BB_MAT101                |
|       29813 |    38027 |        309 | BB_MAT250                |
|       29814 |    28844 |        302 | BB_ENG101                |
|       29814 |    27615 |        384 | BB_MS-ACC101             |
|       29814 |    27616 |        385 | BB_MS-ACC102             |
|       29814 |    27615 |        385 | BB_MS-ACC102             |
|       29814 |    27614 |        409 | BB_MS-MAT101             |
|       29814 |    27584 |        410 | BB_MS-MAT150             |
|       29815 |    27592 |        384 | BB_MS-ACC101             |
|       29815 |    27593 |        384 | BB_MS-ACC101             |
|       29815 |    27594 |        384 | BB_MS-ACC101             |
|       29815 |    27599 |        385 | BB_MS-ACC102             |
|       29815 |    27592 |        402 | BB_MS-ECON101            |
|       29815 |    27593 |        402 | BB_MS-ECON101            |
|       29815 |    27594 |        402 | BB_MS-ECON101            |
|       29815 |    27596 |        403 | BB_MS-ECON102            |
|       29815 |    27598 |        404 | BB_MS-ENG099             |
|       29815 |    27588 |        405 | BB_MS-ENG101             |
|       29815 |    27595 |        406 | BB_MS-ENG102             |
|       29815 |    27589 |        408 | BB_MS-MAT099             |
|       29815 |    27585 |        409 | BB_MS-MAT101             |
|       29815 |    27589 |        410 | BB_MS-MAT150             |
|       29815 |    27589 |        411 | BB_MS-MAT201             |
+-------------+----------+------------+--------------------------+

以下SELECT允许我确定客户多次订购产品的情况......

select orders1.customer_id as dupe_customer_id, items1.product_id as dupe_product_id, count(*) as duplicates
from orders orders1, order_items items1
where orders1.status = 'complete' 
    and orders1.customer_id is not null
    and orders1.entity_id = items1.order_id
group by orders1.customer_id, items1.product_id
having duplicates > 1;

结果......

+------------------+-----------------+------------+
| dupe_customer_id | dupe_product_id | duplicates |
+------------------+-----------------+------------+
|            29814 |             385 |          2 |
|            29815 |             384 |          3 |
|            29815 |             402 |          3 |
+------------------+-----------------+------------+

我想要解决的是如何将这些组合在一起以便我只在第一个选择中获得那些符合第二个选择条件的项目,这样输出就像......

+-------------+----------+------------+--------------------------+
| customer_id | order_id | product_id | sku                      |
+-------------+----------+------------+--------------------------+
|       29814 |    27616 |        385 | BB_MS-ACC102             |
|       29814 |    27615 |        385 | BB_MS-ACC102             |
|       29815 |    27592 |        384 | BB_MS-ACC101             |
|       29815 |    27593 |        384 | BB_MS-ACC101             |
|       29815 |    27594 |        384 | BB_MS-ACC101             |
|       29815 |    27592 |        402 | BB_MS-ECON101            |
|       29815 |    27593 |        402 | BB_MS-ECON101            |
|       29815 |    27594 |        402 | BB_MS-ECON101            |
+-------------+----------+------------+--------------------------+

请注意,结果集的主要标准是customer_id和product_id的任意组合必须多次出现。

我正在努力将它们结合起来。我的尝试导致一个(或多个)列在结果中的每一行都重复了不正确的数据。

我已经掌握了MySQL关于这种类型的SELECT的知识,过去一小时的搜索没有产生任何结果。

2 个答案:

答案 0 :(得分:1)

尝试尝试这样的尝试:

SELECT orders.customer_id
    ,items.order_id
    ,items.product_id
    ,items.sku 
FROM orders AS orders
INNER JOIN order_items AS items ON orders.entity_id = items.order_id
WHERE (orders.customer_id,items.product_id) IN (
    SELECT orderSub.customer_id
        ,itemSub.product_id
    FROM orders AS orderSub
    INNER JOIN order_items AS itemSub ON orderSub.entity_id = itemSub.order_id
    WHERE orderSub.status = 'complete' 
        AND orderSub.customer_id IS NOT NULL
    GROUP BY orderSub.customer_id
        ,itemSub.product_id
    HAVING COUNT(*) > 1;
);

它将查询作为子列查询提供给要使用的IN子句的多列匹配。这是我的头脑,因为我不确定MySQL是否支持这种语法,但它适用于Teradata和DB2。

由于性能原因,我还将您的查询转换为最大化ANSI合规性,因此如果它看起来不同于WHERE IN子句,那就是原因。

答案 1 :(得分:0)

在PlantTheldea的解决方案的帮助下,这是我最终想到的。我的解决方案还有其他左连接,以提供我正在寻找的完整报告。 (它们与原始问题无关。但是,将它们包含在此处更容易,而不是尝试编辑它们。)

CREATE TEMPORARY TABLE temp_customer_items 
    (PRIMARY KEY my_pkey (customer_id, product_id)) 
SELECT orderSub.customer_id 
    , itemSub.product_id 
FROM orders AS orderSub
INNER JOIN items AS itemSub 
    ON orderSub.entity_id = itemSub.order_id 
WHERE orderSub.entity_id = itemSub.order_id 
    AND orderSub.customer_id IS NOT NULL 
    AND orderSub.status = 'complete'  
    AND itemSub.product_type = 'simple' 
GROUP BY orderSub.customer_id 
    , itemSub.product_id 
HAVING COUNT(*) > 1;
SELECT orders.customer_id AS student_id
    , fname.value AS first_name 
    , mname.value AS middle_name 
    , lname.value AS last_name 
    , customers.email 
    , items.product_id 
    , items.sku AS product_sku
    , orders.increment_id AS order_id 
    , orders.updated_at AS order_date
FROM orders AS orders 
LEFT JOIN customers AS customers 
    ON orders.customer_id = customers.entity_id 
INNER JOIN items AS items  
    ON orders.entity_id = items.order_id 
    WHERE (orders.customer_id,items.product_id) IN ( 
        SELECT temp_customer_items.customer_id 
            , temp_customer_items.product_id 
        FROM temp_customer_items )
ORDER BY last_name ASC 
    , first_name ASC 
    , middle_name ASC 
    , orders.updated_at DESC 
    , items.order_id ASC;
DROP TEMPORARY TABLE temp_customer_items;