在 MySQL 中,ON 和 WHERE 都用于过滤数据,但它们的使用场景和作用有所不同,尤其是在涉及 JOIN 操作时。下面通过具体的例子来说明它们的区别。
1. ON 的作用
ON 用于指定表之间的连接条件,决定哪些行应该被连接在一起。它在 JOIN 操作时生效。
示例:
假设有两个表:
orders 表:存储订单信息。
+---------+------------+-------------+
| order_id| order_date | customer_id |
+---------+------------+-------------+
| 1 | 2023-01-01 | 101 |
| 2 | 2023-02-01 | 102 |
| 3 | 2023-03-01 | 103 |
+---------+------------+-------------+
customers 表:存储客户信息。
+-------------+------------+
| customer_id | name |
+-------------+------------+
| 101 | Alice |
| 102 | Bob |
| 103 | Charlie |
+-------------+------------+
使用 ON 进行连接:
SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;
结果:
+---------+------------+-------------+-------------+-------+
| order_id| order_date | customer_id | customer_id | name |
+---------+------------+-------------+-------------+-------+
| 1 | 2023-01-01 | 101 | 101 | Alice |
| 2 | 2023-02-01 | 102 | 102 | Bob |
| 3 | 2023-03-01 | 103 | 103 | Charlie|
+---------+------------+-------------+-------------+-------+
ON 条件指定了 orders.customer_id = customers.customer_id,决定了哪些行应该被连接在一起。
2. WHERE 的作用
WHERE 用于过滤查询结果集中的行。它在连接操作之后生效。
示例:
继续使用上面的 orders 和 customers 表,现在需要查询 order_date 大于 2023-01-01 的订单。
SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
WHERE orders.order_date > '2023-01-01';
结果:
+---------+------------+-------------+-------------+-------+
| order_id| order_date | customer_id | customer_id | name |
+---------+------------+-------------+-------------+-------+
| 2 | 2023-02-01 | 102 | 102 | Bob |
| 3 | 2023-03-01 | 103 | 103 | Charlie|
+---------+------------+-------------+-------------+-------+
WHERE条件过滤了order_date大于2023-01-01的记录。
3. ON 和 WHERE 的区别
场景 1:INNER JOIN 中的 ON 和 WHERE
在 INNER JOIN 中,ON 和 WHERE 的效果通常是相同的,因为 INNER JOIN 只返回满足连接条件的行。
示例:
-- 使用 ON 条件
SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
AND orders.order_date > '2023-01-01';
-- 使用 WHERE 条件
SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
WHERE orders.order_date > '2023-01-01';
结果:
+---------+------------+-------------+-------------+-------+
| order_id| order_date | customer_id | customer_id | name |
+---------+------------+-------------+-------------+-------+
| 2 | 2023-02-01 | 102 | 102 | Bob |
| 3 | 2023-03-01 | 103 | 103 | Charlie|
+---------+------------+-------------+-------------+-------+
在 INNER JOIN 中,ON 和 WHERE 的结果是相同的。
场景 2:LEFT JOIN 中的 ON 和 WHERE
在 LEFT JOIN 中,ON 和 WHERE 的效果可能不同,因为 LEFT JOIN 会保留左表中的所有行,即使右表中没有匹配的行。
示例 :
假设 orders 表中有一条记录没有对应的 customer_id:
+---------+------------+-------------+
| order_id| order_date | customer_id |
+---------+------------+-------------+
| 1 | 2023-01-01 | 101 |
| 2 | 2023-02-01 | 102 |
| 3 | 2023-03-01 | 103 |
| 4 | 2023-04-01 | NULL | -- 没有对应的 customer_id
+---------+------------+-------------+
使用 ON 条件:
SELECT *
FROM orders
LEFT JOIN customers ON orders.customer_id = customers.customer_id
AND customers.name = 'Alice';
结果:
+---------+------------+-------------+-------------+-------+
| order_id| order_date | customer_id | customer_id | name |
+---------+------------+-------------+-------------+-------+
| 1 | 2023-01-01 | 101 | 101 | Alice |
| 2 | 2023-02-01 | 102 | NULL | NULL |
| 3 | 2023-03-01 | 103 | NULL | NULL |
| 4 | 2023-04-01 | NULL | NULL | NULL |
+---------+------------+-------------+-------------+-------+
ON 条件保留了所有 orders 表中的行,即使 customers.name 不是 Alice
使用 WHERE 条件:
SELECT *
FROM orders
LEFT JOIN customers ON orders.customer_id = customers.customer_id
WHERE customers.name = 'Alice';
结果:
+---------+------------+-------------+-------------+-------+
| order_id| order_date | customer_id | customer_id | name |
+---------+------------+-------------+-------------+-------+
| 1 | 2023-01-01 | 101 | 101 | Alice |
+---------+------------+-------------+-------------+-------+
WHERE 条件过滤了结果集,只返回 customers.name = 'Alice' 的行
4. 总结
-
ON:用于指定连接条件,决定哪些行应该被连接在一起。它在连接操作时生效。 -
WHERE:用于过滤查询结果,决定哪些行应该被返回。它在连接操作之后生效。 -
在
INNER JOIN中,ON和WHERE的效果通常是相同的。 -
在
LEFT JOIN或RIGHT JOIN中,ON和WHERE的效果可能不同,需要根据实际需求谨慎选择。