专业剑 : SQL - LEFT JOIN


LEFT JOIN 条件放在ON后面还是WHERE后面

通常是放在ON后面,因为LEFT JOIN的设计是返回左表的所有记录,即使右表没有记录。

如果条件放在WHERE后面,会过滤结果集,可能会改变查询的结果,偏离期望。

例子

CUSTOMER

IDNAME
1A
2B
3C

ORDERS

IDCUSTOMER_IDAMOUNT
101110
102120
103230

SELECT c.ID as CUSTOMER_ID, c.NAME, o.ID as ORDER_ID, o.AMOUNT

FROM CUSTOMER c

LEFT JOIN ORDERS o

ON c.ID = o.CUSTOMER_ID AND o.AMOUNT > 10

查询结果:

CUSTOMER_IDNAMEORDER_IDAMOUNT
1A10220
2B10330
3Cnullnull


SELECT c.ID, c.NAME, o.ID, o.AMOUNT

FROM CUSTOMER c

LEFT JOIN ORDERS o

ON c.ID = o.CUSTOMER_ID 

查询结果:

CUSTOMER_IDNAMEORDER_IDAMOUNT
1A10110
1A10220
2B10330
3Cnullnull


SELECT c.ID, c.NAME, o.ID, o.AMOUNT

FROM CUSTOMER c

LEFT JOIN ORDERS o

ON c.ID = o.CUSTOMER_ID WHERE o.AMOUNT > 10

查询结果:

CUSTOMER_IDNAMEORDER_IDAMOUNT
1A10220
2B10330


多个LEFT JOIN

需要从多个表中获取相关数据时,可以使用多个LEFT JOIN。

SELECT 列名 FROM 表1
LEFT JOIN 表2 ON 表1.列 = 表2.列
LEFT JOIN 表3 ON 表1.列 = 表3.列 或 表2.列 = 表3.列 ...


假设有三个表:

  • customers(客户表)
  • orders(订单表)
  • payments(付款表)

需要哦返回所有客户的订单和付款数据,包括没有订单或者没有付款的客户。

SELECT 
    c.customer_id,
    c.customer_name,
    o.order_id,
    o.order_date,
    p.amount,
    p.payment_date
FROM 
    customers c
LEFT JOIN 
    orders o ON c.customer_id = o.customer_id
LEFT JOIN 
    payments p ON o.order_id = p.order_id



注意:

1. 执行顺序:SQL会按照FROM子句中表的顺序依次执行LEFT JOIN

2. 性能影响:每个LEFT JOIN都会增加查询的复杂度,可能影响性能

3. NULL值处理:当右表没有匹配记录时,结果中该表的所有列将为NULL

4. 连接条件:确保连接条件正确,避免笛卡尔积

替代方案:

如果只需要左表的记录,而不需要右表的部分数据,可以考虑使用子查询或EXISTS子句来提高性能。


-- 使用EXISTS替代LEFT JOIN的示例
SELECT c.*
FROM customers c
WHERE EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
)