3

我希望使用 LEFT JOIN 查询从具有一对多关系的两个表中获取一些结果,但根据“孩子”的数量限制结果集。我有两个表结构如下:

customers
id    name    ...
1     "bob"   ...
2     "jill"  ...

orders
id    customer_id    ...
100   1              ...
101   2              ...
102   1              ...

(表中的其余数据与此查询无关。)

我想做的是获取所有客户 ID 及其订单 ID,按客户排序,但仅限于下了多个订单的客户。在此示例中,结果如下所示:

cust_id    order_id
1          100
1          102

我从一个基本的 LEFT JOIN 开始,将订单 ID 与他们的客户配对,但不知道如何排除所有未订购至少两次的客户。

SELECT 
    `customers`.`id` AS `cust_id`,
    `orders`.`id` AS `order_id`
FROM
    `customers`
LEFT JOIN `orders` ON
    `customers`.`id` = `orders`.`customer_id`
ORDER BY
    `cust_id`

谢谢大家。

4

5 回答 5

7

一种方法是创建一个内联视图,以获取拥有多个订单的客户及其内部连接。如果您不喜欢 JOIN,您也可以执行 IN 或 EXISTS

SELECT 
    `customers`.`id` AS `cust_id`,
    `orders`.`id` AS `order_id`
FROM
    `customers`
LEFT JOIN `orders` ON
    `customers`.`id` = `orders`.`customer_id`
INNER JOIN 
      (SELECT `customer_id `    
       FROM `orders`
       GROUP BY `customer_id`    
       HAVING COUNT(id) > 1) as `morethanone`
On
    `customer`.`id`  = `morethanone`.`custmor_id`
ORDER BY
    `cust_id`
于 2012-05-08T22:05:17.040 回答
1

首先,您不需要将联接保留在外部,因为该联接与内部联接之间的唯一区别是包括没有订单的客户,并且您不需要它们在结果中,因为他们的订单少于两个.

SELECT customers.id AS `cust_id`, orders.id AS `order_id`
FROM customers
     INNER JOIN orders ON `customers`.`id` = `orders`.`customer_id`
     INNER JOIN orders count_orders ON customers.id = count_orders.customer_id
GROUP BY count_orders.id, orders.id
HAVING count(count_orders.id) >= 2
ORDER BY `cust_id`
于 2012-05-08T22:12:16.880 回答
1

嘿,我想我有点慢,但无论如何我都会发布我的答案。它略有不同,但仍然有效。

SELECT `customers`.`id` AS `cust_id` , count( orders.id ) AS count_orders
FROM `customers`
JOIN `orders` ON `customers`.`id` = `orders`.`customer_id`
GROUP BY customers.id
HAVING count( orders.id ) >1
ORDER BY `cust_id`
于 2012-05-08T22:18:24.627 回答
0

如果您排除尚未订购的客户,那么 LEFT JOIN 是不必要的,不是吗?

由于您需要结果集中的订单 ID,因此需要首先运行 COUNT 查询。

在 SQL Server 2005+ 中,CTE 将完成计数查询,然后可以根据该计数查询生成您想要的结果集:

WITH customerWithMoreThanOneOrder AS
(
    SELECT 
        `customers`.`id` AS `cust_id`
    FROM
        `customers`
    INNER JOIN `orders` ON
        `customers`.`id` = `orders`.`customer_id`
    GROUP BY 
        `customers`.`id`
    HAVING COUNT(0) > 1
)

SELECT 
    `customers`.`id` AS `cust_id`,
    `orders`.`id` AS `order_id`
FROM
    `customers`
INNER JOIN `orders` ON
    `customers`.`id` = `orders`.`customer_id`
WHERE `customers`.`id` IN (SELECT cust_id FROM customerWithMoreThanOneOrder)
ORDER BY
    `cust_id`

如果您使用的数据库不支持这种结构,那么只需将计数查询放在 IN 子查询的括号中,如下所示:

SELECT 
    `customers`.`id` AS `cust_id`,
    `orders`.`id` AS `order_id`
FROM
    `customers`
INNER JOIN `orders` ON
    `customers`.`id` = `orders`.`customer_id`
WHERE `customers`.`id` IN (SELECT 
                               `customers`.`id` AS `cust_id`
                           FROM
                               `customers`
                           INNER JOIN `orders` ON
                               `customers`.`id` = `orders`.`customer_id`
                           GROUP BY 
                               `customers`.`id`
                           HAVING COUNT(0) > 1)
ORDER BY
    `cust_id`

如果您有任何问题,请告诉我

于 2012-05-08T22:16:53.190 回答
0

作为其他答案的替代方案,您可以使用 IN 子句。

SELECT 
    `customers`.`id` AS `cust_id`,
    `orders`.`id` AS `order_id`
FROM
    `customers`
LEFT JOIN `orders` ON
    `customers`.`id` = `orders`.`customer_id`
WHERE `customer_id` IN (SELECT `customer_id` FROM `orders` GROUP BY `customer_id` HAVING COUNT(*) > 1)
ORDER BY
    `cust_id`
于 2012-05-09T00:32:46.260 回答