SQL ON与WHERE区别
在 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
的效果可能不同,需要根据实际需求谨慎选择。