说句实话企业中都用的索引jion似乎已经过时

场景一(基础):订单与用户关联(两表内联结)

  • 业务需求:运营需要导出一份“已支付(PAID)”的订单列表,展示订单流水号(order_sn)、下单用户名(username)、下单手机号(phone)以及订单总金额(total_amount)。

  • 考查重点:基础 INNER JOIN 与条件过滤 WHERE。

  • 解题思路:以 orders 为基准表,利用 user_id 字段内连 users 表,并在 WHERE 中过滤已支付状态。

SQL 答案:

SQL

SELECT 
    o.order_sn,
    u.username,
    u.phone,
    o.total_amount
FROM orders o
JOIN users u ON o.user_id = u.user_id
WHERE o.order_status = 'PAID';

场景二(进阶):订单购物清单全景(四表全链路级联)

  • 业务需求:仓库打单系统需要打印流水号为 'ORD20261001001' 的完整发货单明细,展示下单用户姓名(username)、商品名称(product_name)、购买单价(unit_price)、购买数量(quantity)以及单项小计金额(unit_price * quantity)。

  • 考查重点:通过中间联结表 order_items 将多对多关系打通,实现 4 表级联与计算字段。

  • 解题思路:关联链路为 orders ➔ users,同时 orders ➔ order_items ➔ products。

SQL 答案:

SQL

SELECT 
    u.username,
    p.product_name,
    oi.unit_price,
    oi.quantity,
    (oi.unit_price * oi.quantity) AS subtotal
FROM orders o
JOIN users u ON o.user_id = u.user_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE o.order_sn = 'ORD20261001001';

场景三(实战):沉默用户排查(左外联结与空值过滤)

  • 业务需求:市场部要做召回拉新活动,需要找出系统注册后从未下过任何订单的用户,展示其用户名(username)和手机号(phone)。

  • 考查重点:LEFT JOIN(左外联结)与 WHERE ... IS NULL 的排他筛选。

  • 解题思路:

    • 如果用 INNER JOIN,没有订单的用户会被直接剔除。

    • 必须用 users 做左表,LEFT JOIN 订单表 orders。

    • 未下过单的用户,其对应的订单字段都会补 NULL,通过 WHERE o.order_id IS NULL 即可精准锁定。

SQL 答案:

SQL

SELECT 
    u.username,
    u.phone
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.order_id IS NULL;

(在提供的 SQL 数据中,王五与赵六从未下过单,查询将准确返回他们俩的信息)

场景四(高阶):用户消费贡献与聚合(外联结 + 分组统计)

  • 业务需求:财务需要统计系统中所有用户的历史已支付消费总额,展示:用户ID(user_id)、用户名(username)、已支付总金额(无消费或没有已支付订单的用户显示为 0.00),并按总金额降序排列。

  • 考查重点:

    1. LEFT JOIN 的过滤条件是写在 ON 还是 WHERE(写在 WHERE 会导致左表未消费用户被错误过滤,破坏外联结)。

    2. GROUP BY 多表聚合。

    3. 使用 IFNULL 或 COALESCE 处理无消费时的 NULL 值。

SQL 答案:

SQL

SELECT 
    u.user_id,
    u.username,
    IFNULL(SUM(o.total_amount), 0.00) AS total_spent
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id AND o.order_status = 'PAID'
GROUP BY u.user_id, u.username
ORDER BY total_spent DESC;

(解析关键点:AND o.order_status = 'PAID' 必须跟在 ON 后面,这样即使该用户没有已支付订单,主表用户仍然会被完整保留,金额被聚合为 NULL 后由 IFNULL 转为 0.00)