sql语句中left join和inner join中的on与where的区别分析

转载于:http://www.cnblogs.com/wanglu/p/4390612.html 

 sql语句中left join和inner join中的on与where的区别分析

关于SQL SERVER的表联接查询INNER JOIN 、LEFT JOIN和RIGHT JOIN,经常会用到ON和WHERE的条件查询,以前用的时候有时是凭感觉的,总是没有搞清楚,今日亲自测试了下,理解到了一些内容,在此分享。

要测试,首先我们来创建三张表,数据库就根据自己的情况而定

创建表TestJoinOnOrWhere_A、TestJoinOnOrWhere_B、TestJoinOnOrWhere_C

/****** Object:  Table [dbo].[TestJoinOnOrWhere_A]    Script Date: 2015/4/3 14:34:41 ******/
CREATE TABLE [dbo].[TestJoinOnOrWhere_A](
    [id] [int] NULL,
    [value] [int] NULL
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[TestJoinOnOrWhere_B]    Script Date: 2015/4/3 14:34:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TestJoinOnOrWhere_B](
    [id] [int] NULL,
    [value] [int] NULL
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[TestJoinOnOrWhere_C]    Script Date: 2015/4/3 14:34:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TestJoinOnOrWhere_C](
    [id] [int] NULL,
    [value] [int] NULL
) ON [PRIMARY]

表创建好了然后我们添加几条数据

INSERT [dbo].[TestJoinOnOrWhere_A] ([id], [value]) VALUES (1, 1)
INSERT [dbo].[TestJoinOnOrWhere_A] ([id], [value]) VALUES (2, 1)
INSERT [dbo].[TestJoinOnOrWhere_A] ([id], [value]) VALUES (3, 2)
INSERT [dbo].[TestJoinOnOrWhere_B] ([id], [value]) VALUES (1, 1)
INSERT [dbo].[TestJoinOnOrWhere_B] ([id], [value]) VALUES (2, 3)
INSERT [dbo].[TestJoinOnOrWhere_B] ([id], [value]) VALUES (3, 4)
INSERT [dbo].[TestJoinOnOrWhere_C] ([id], [value]) VALUES (1, 1)
INSERT [dbo].[TestJoinOnOrWhere_C] ([id], [value]) VALUES (2, 2)
INSERT [dbo].[TestJoinOnOrWhere_C] ([id], [value]) VALUES (3, 3)

现在我们开始测试

语句1:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND a.value = 1
语句2:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id

结果1:

id   value  id    value

-------------------------------
1    1       1     1
2    1       2     3
3    2      NULL NULL

结果2

id   value  id    value

-------------------------------
1    1       1     1
2    1       2     3
3    2       3     4

在网上查询到,有的人说a.value = 1没有生效,其实不然,它已经生效,只是在左联接查询时,左表的数据是不会受影响,只有右表的数据会根据a.value = 1条件取出左表(a表)Value为1的行,通过上面两个语句的结果就可以看出,那么我们用右表筛选条件会出现什么呢?看看下面语句

语句3:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND b.value = 1

结果3:

id   value  id    value

-------------------------------
1    1       1     1
2    1       NULL NULL
3    2       NULL NULL

以上结果看出,也只是影响了右表的数据

语句4:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN dbo.TestJoinOnOrWhere_B AS b ON  a.value = 1

结果4:

id   value  id    value

-------------------------------
1    1       1     1
1    1       2     3
1    1       3     4
2    1       1     1
2    1       2     3
2    1       3     4
3    2       NULL NULL

从上面语句结果看出,也只影响了右表的数据(取出所有a表value对应为1的b表数据)

所以在左联接查询时ON后面的条件只会影响右表,相反右联接查询影响的就是左边的表数据

如果用WHERE呢?我们看下下面的语句

语句5:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id where a.value = 1

语句6:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id where b.value = 1

结果5:

id   value  id    value

-------------------------------
1    1       1     1
2    1       2     3

结果6:

id   value  id    value

-------------------------------
1    1       1     1

可以从结果看出,这个影响的结果就是全部的表,就相当于通过ON条件联接查询查询的结果,然后通过WHERE后面的条件取总体筛选

对于INNER JOIN 的ON条件会怎样影响呢?先看下面语句执行结果

语句7:  SELECT * FROM dbo.TestJoinOnOrWhere_A AS a INNER JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND a.value = 1
语句8:  SELECT * FROM dbo.TestJoinOnOrWhere_A AS a INNER JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND b.value = 1
语句9:  SELECT * FROM dbo.TestJoinOnOrWhere_A AS a INNER JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id WHERE a.value = 1
语句10:SELECT * FROM dbo.TestJoinOnOrWhere_A AS a INNER JOIN dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id WHERE b.value = 1

结果7/9:

id   value  id    value

-------------------------------
1    1       1     1
2    1       2     3

结果8/10:

id   value  id    value

-------------------------------
1    1       1     1

上面通过WHERE和ON查询出来的结果是一样的,由此可看出,INNER JOIN 的ON条件和WHERE条件影响的都是一个效果,影响整体的查询结果。

下面我们再来看下对于LEFT JOIN的三表查询对于WHERE和ON影响的结果

语句11:SELECT a.id AS a_id,a.value AS a_value,b.id AS b_id,b.value AS b_value,c.id AS c_id,c.value AS c_value FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN   dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND a.value = 1  LEFT JOIN dbo.TestJoinOnOrWhere_C AS c ON b.id = c.id
语句12:SELECT a.id AS a_id,a.value AS a_value,b.id AS b_id,b.value AS b_value,c.id AS c_id,c.value AS c_value FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN  dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND b.value = 1  LEFT JOIN dbo.TestJoinOnOrWhere_C AS c ON b.id = c.id 
语句13:SELECT a.id AS a_id,a.value AS a_value,b.id AS b_id,b.value AS b_value,c.id AS c_id,c.value AS c_value FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN  dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND a.value = 1  LEFT JOIN dbo.TestJoinOnOrWhere_C AS c ON b.id = c.id AND b.value = 1
语句14:SELECT a.id AS a_id,a.value AS a_value,b.id AS b_id,b.value AS b_value,c.id AS c_id,c.value AS c_value FROM dbo.TestJoinOnOrWhere_A AS a LEFT JOIN  dbo.TestJoinOnOrWhere_B AS b ON a.id = b.id AND a.value = 1  LEFT JOIN dbo.TestJoinOnOrWhere_C AS c ON b.id = c.id AND c.value = 2

结果11:

a_id  a_value  b_id  b_value  c_id   c_value

-----------------------------------------------------
1     1           1        1          1       1
2     1           2        3          2       2
3     2           NULL   NULL    NULL  NULL

结果12:

a_id  a_value  b_id  b_value  c_id   c_value

-----------------------------------------------------
1     1           1        1          1       1
2     1           NULL   NULL    NULL  NULL
3     2           NULL   NULL    NULL  NULL

结果13:

a_id  a_value  b_id  b_value  c_id   c_value

-----------------------------------------------------
1     1           1        1          1       1
2     1           2        3          NULL  NULL
3     2           NULL   NULL    NULL  NULL

结果14:

a_id  a_value  b_id  b_value  c_id   c_value

-----------------------------------------------------
1     1           1        1          NULL  NULL
2     1           2        3          2        2
3     2           NULL   NULL    NULL  NULL

      通过以上三表数据查询结果,可以看出,LEFT JOIN 查询,对于ON的单独表条件始终只会影响条件表的右表(如,a.value=1会影响b表关联的a表value字段值为1的行,并不会限制a表的数据只显示value=1的行),RIGHT JOIN 影响效果恰恰相反

      在使用ON条件时LEFT JOIN影响的是右侧的第二张第三张表,并不会对最左侧的表影响,所以对于a,b,c,三张表,a表数据是不受ON条件影响的,只会影响联接查询后的b或c数据

而WHERE就相当于在WHERE条件之前查询的数据当着一个表,然后通过WHERE条件进行筛选数据,所以影响的是整体。

<think>首先,用户的问题是关于SQLLEFT JOIN的使用方法示例。我需要基于系统指令来构建我的回答。 系统级指令关键点: - 所有行内数学表达式使用$...$格式,但这里没有数学内容,所以可能不需要。 - 独立公式使用$$...$$格式,但SQL不是数学公式,所以可能不适用。 - LaTeX语法正确,但SQL查询不需要LaTeX。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,逐步解决问题。 - 参考站内引用:用户提供了引用[1]到[4],这些是关于SQL LEFT JOIN的引用。我需要参考这些来构建回答。 用户提供的引用: - [^1]: SQL LEFT JOIN 简介。基本语法示例。 - [^2]: SQL LEFT JOIN 关键字的使用方法注意事项。基本语法NULL填充。 - [^3]: SQL中的LEFT JOIN、RIGHT JOININNER JOIN。介绍三种JOIN类型。 - [^4]: SQLINNER JOINLEFT JOIN区别用法。基本概念区别。 用户的问题: "我想理解SQLLEFT JOIN的使用方法 请问SQL LEFT JOIN 用法示例" 我的回答需要: 1. 结构清晰,逐步解释LEFT JOIN。 2. 包括用法示例。 3. 使用中文。 4. 在引用段落末尾添加引用标识。 5. 生成相关问题。 结构建议: - 先介绍LEFT JOIN的概念。 - 解释基本语法。 - 提供示例。 - 讨论注意事项或其他JOIN区别。 - 最后生成相关问题。 添加引用:当引用信息时,在段落末尾加[^1]等。例如,如果我从引用[1]取语法,就在那段末尾加[^1]。 生成相关问题:在回答结束后,添加"§§相关问题§§"部分,列出几个相关问题。 确保回答真实可靠:基于提供的引用标准SQL知识。 大纲回答: 1. **介绍LEFT JOIN**:解释什么是LEFT JOIN,它的作用(返回左表所有行,右表匹配或无匹配时用NULL填充)。 - 参考引用[1],[2],[3]。 2. **基本语法**:给出SQL语法。 - 例如:SELECT columns FROM table1 LEFT JOIN table2 ON condition; - 参考引用[1],[2]。 3. **示例**:提供一个简单的示例。 - 例如,两个表:CustomersOrders。 - 查询所有客户及其订单,如果没有订单则显示NULL。 - 参考引用[1],[2]。 4. **注意事项**:讨论NULL值、性能等。 - 参考引用[2]。 5. **其他JOIN区别**:简要比较INNER JOINRIGHT JOIN。 - 参考引用[3],[4]。 6. **生成相关问题**:在最后添加相关问题部分。 使用中文:整个回答用中文。 添加引用标识: - 例如:当描述语法时,说"基本语法是:SELECT ... FROM ... LEFT JOIN ... ON ... [^1]"。 最终输出格式: - 回答内容。 - §§相关问题§§ - 相关问题列表。</think>### SQL LEFT JOIN 用法示例 在 SQL 中,LEFT JOIN(左连接)是一种常见的表连接操作,用于返回左表(table1)的所有行,无论右表(table2)是否有匹配的行。如果右表没有匹配的行,结果集中右表的列将用 NULL 值填充。这使得 LEFT JOIN 特别适合查询“所有左表记录及其可能关联的右表记录”的场景,例如获取所有客户及其订单(即使某些客户没有订单)[^2]。下面我将逐步解释 LEFT JOIN 的用法、语法示例,确保内容清晰易懂。 #### 1. LEFT JOIN 的基本概念 - **作用**:LEFT JOIN 确保左表的所有行都出现在结果中。如果右表有匹配的行(基于连接条件),则显示匹配数据;如果没有匹配,右表列返回 NULL。 - **适用场景**:常用于查询“主表”数据时,需要包含所有记录,即使“从表”无关联数据。例如,在客户管理系统、订单跟踪或数据分析中[^1][^3]。 - **其他 JOIN区别**: - **INNER JOIN**:只返回两个表都有匹配的行。 - **RIGHT JOIN**:返回右表所有行,左表无匹配时用 NULL 填充。 - LEFT JOIN 优先保证左表完整性,而 INNER JOIN 更注重数据交集[^3][^4]。 #### 2. LEFT JOIN 的基本语法 LEFT JOIN 的语法结构如下: ```sql SELECT column_names FROM table1 LEFT JOIN table2 ON table1.column_name = table2.column_name; ``` - **参数说明**: - `column_names`:要选择的列名(可以是具体列如 `table1.id`, `table2.name`,或通配符 `*`)。 - `table1`:左表名称(主表)。 - `table2`:右表名称(从表)。 - `ON` 子句:指定连接条件,通常是两个表中具有相同值的列(如主键-外键关系)[^1][^2]。 - **注意事项**: - **NULL 值处理**:当右表无匹配时,结果中右表列显示 NULL。需在查询中处理 NULL,以避免逻辑错误。 - **性能优化**:对大型表使用 LEFT JOIN 时,确保连接列有索引,否则可能导致查询缓慢[^2][^4]。 - **别名使用**:建议为表指定别名(如 `FROM customers AS c`),以提高可读性。 #### 3. LEFT JOIN 示例 假设有两个表:`customers`(客户表) `orders`(订单表)。`customers` 表包含客户 ID 姓名,`orders` 表包含订单 ID 客户 ID(外键)。我们要查询所有客户及其订单信息,包括没有订单的客户。 - **表结构**: - `customers` 表: | customer_id | customer_name | |-------------|---------------| | 1 | 张三 | | 2 | 李四 | | 3 | 王五 | - `orders` 表: | order_id | customer_id | amount | |----------|-------------|--------| | 101 | 1 | 100 | | 102 | 1 | 200 | | 103 | 2 | 150 | - **查询示例**:使用 LEFT JOIN 获取所有客户及其订单(无订单时显示 NULL)。 ```sql SELECT c.customer_name, o.order_id, o.amount FROM customers AS c LEFT JOIN orders AS o ON c.customer_id = o.customer_id; ``` - **结果解释**: | customer_name | order_id | amount | |---------------|----------|--------| | 张三 | 101 | 100 | | 张三 | 102 | 200 | | 李四 | 103 | 150 | | 王五 | NULL | NULL | 在这个结果中: - “张三”有两条订单记录(匹配成功)。 - “李四”有一条订单记录(匹配成功)。 - “王五”没有订单,因此 `order_id` `amount` 显示 NULL(LEFT JOIN 确保了左表所有行被保留)[^1][^2]。 #### 4. 注意事项最佳实践 - **避免数据冗余**:如果左表有重复行,LEFT JOIN 可能返回多行结果。使用 `DISTINCT` 或子查询去重。 - **结合 WHERE 子句**:可以在 LEFT JOIN 后添加 WHERE 条件过滤结果。例如,只查询没有订单的客户: ```sql SELECT c.customer_name FROM customers AS c LEFT JOIN orders AS o ON c.customer_id = o.customer_id WHERE o.order_id IS NULL; ``` - ** INNER JOIN 对比**:INNER JOIN 会排除“王五”这样的无匹配记录,而 LEFT JOIN 会包含它们。这体现了 LEFT JOIN 在数据完整性上的优势[^4]。 - **实际应用**:LEFT JOIN 广泛用于报表生成、数据分析 Web 应用中,例如在电商平台展示所有用户及其购买历史[^3]。 通过以上步骤,您应该能理解 LEFT JOIN 的核心用法。如果需要更复杂的示例(如多表连接),可以参考 SQL 文档或练习工具如 SQL Fiddle。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值