You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求高效SQL查询:获取付清全部订单或未下单的客户姓名

Alright, let's tackle this problem to get the exact customer groups you need—those who've paid for every single order they placed, plus those who never placed any orders at all. Below are two efficient SQL query approaches, tailored to the one-to-many relationship between Customer and Order tables you described.

Assumptions About Table Structure

First, let's confirm the table fields (adjust if your actual schema differs slightly):

  • Customer: Has customer_id (primary key) and name (the field we need to retrieve)
  • Order: Has order_id (primary key), customer_id (foreign key linking to Customer), and payment_status (only 'PAID' or 'UNPAID')

Approach 1: LEFT JOIN + Aggregation

This method uses a left join to include all customers, then groups them to check order statuses:

SELECT c.name
FROM Customer c
LEFT JOIN `Order` o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.name
HAVING 
    -- Customers who never placed an order (no associated order records)
    COUNT(o.order_id) = 0
    OR
    -- Customers with all orders paid: at least one order, and no unpaid orders
    (COUNT(o.order_id) > 0 AND SUM(CASE WHEN o.payment_status = 'UNPAID' THEN 1 ELSE 0 END) = 0);

How This Works:

  • LEFT JOIN ensures we include every customer from the Customer table, even those with no orders.
  • GROUP BY clusters results by individual customer so we can aggregate their order data.
  • The HAVING clause filters for our two target groups:
    1. COUNT(o.order_id) = 0: No orders linked to the customer → fits the "never ordered" group.
    2. The second condition checks that the customer has at least one order, and that there are zero unpaid orders in their history → fits the "all orders paid" group.

Approach 2: Using NOT EXISTS (Optimized for Speed)

Many database optimizers perform extremely well with NOT EXISTS (it uses semi-joins to avoid unnecessary data processing). This approach checks for the absence of specific order conditions:

SELECT c.name
FROM Customer c
WHERE 
    -- Customers who never placed any orders
    NOT EXISTS (SELECT 1 FROM `Order` o WHERE o.customer_id = c.customer_id)
    OR
    -- Customers with no unpaid orders (all orders are paid)
    NOT EXISTS (SELECT 1 FROM `Order` o WHERE o.customer_id = c.customer_id AND o.payment_status = 'UNPAID');

How This Works:

  • The first NOT EXISTS checks that there are no orders linked to the customer.
  • The second NOT EXISTS checks that there are no unpaid orders for the customer (this automatically includes customers with no orders, but combining it with the first condition via OR ensures we cover both groups clearly).

Example Test Case

Let's use sample data to verify:

Customer Table

customer_idname
1Alice
2Bob
3Charlie
4Dave

Order Table

order_idcustomer_idpayment_status
1011PAID
1021PAID
1032UNPAID
1043PAID

Expected Result

name
Alice
Charlie
Dave

Both queries will return these names: Alice and Charlie have all orders paid, Dave never ordered, and Bob is excluded due to an unpaid order.

内容的提问来源于stack exchange,提问作者Rakesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:05:03