问题
现有表EMP和DEPT如下:
EMP
EMPID EMPNAME DEPTID
1 张三 1
2 李四 2
3 王五 2
4 赵六 2
5 孙七 3
DEPT
DEPTID DEPTNAME
1 开发
2 测试
3 需求
4 销售
现在要看开发部门的人员情况。
这个问题只需以EMP.DEPTID等于DEPT.DEPTID为连接条件来连接两张表。一般来说,跨表查询有两种实现方法:ANSI SQL和dialect SQL
方法1
ANSI SQL,使用JOIN…ON…子句。SQL statement如下:
SELECT EMP.* FROM EMP
JOIN DEPT
ON EMP.DEPTID = DEPT.DEPTID
WHERE DEPT.DEPTID = 1
方法2
Dialect SQL,把连接条件和过滤条件都放在WHERE子句里。SQL statement如下:
SELECT EMP.* FROM EMP, DEPT
WHERE EMP.DEPTID = DEPT.DEPTID AND DEPT.DEPTID = 1
这两种方法本身都没有问题。观察这两个SQL语句可见,二者的区别在于前者把连接条件和过滤条件分开了,而后者没有分开。那么问题就来了,连接条件和过滤条件需要分开吗?在ANSI写法下,如果不分开会怎么样?例如下面的SQL statement:
方法3
SELECT EMP.* FROM EMP
JOIN DEPT
ON EMP.DEPTID = DEPT.DEPTID AND DEPT.DEPTID = 1
虽然“DEPT.DEPTID = 1”并不是连接条件,但是这里把它放到ON子句里,也能得到正确的结果。那么WHERE和ON到底有何不同呢?
分析
我上网查了一些资料,自己也做了一些试验。目前得到的结论为,对于内连接(inner join),二者并无不同(至少从结果上看,至于效率就不清楚了)。所以上面的例子中,这三种写法都OK。当然,把过滤条件放在ON子句里,可读性会差很多。
对于外连接,二者还是确有不同的。比如,我要得到某个部门(如开发)的人数,由于有的部门可能没有员工,所以这里必须用外连接。SQL statement如下:
方法一
SELECT DEPT.DEPTID, DEPT.DEPTNAME, COUNT(EMP.EMPID) AS EMPNUMBER
FROM DEPT
LEFT JOIN EMP
ON EMP.DEPTID=DEPT.DEPTID
WHERE DEPTNAME = '开发'
GROUP BY DEPT.DEPTID, DEPT.DEPTNAME
结果如下:
DEPTID DEPTNAME EMPNUMBER
1 开发 1
这里连接条件和过滤条件就不能混用,如果把过滤条件也放到连接条件里,SQL statement如下:
方法二
SELECT DEPT.DEPTID, DEPT.DEPTNAME, COUNT(EMP.EMPID) AS EMPNUMBER
FROM DEPT
LEFT JOIN EMP
ON EMP.DEPTID=DEPT.DEPTID AND DEPTNAME = '开发'
GROUP BY DEPT.DEPTID, DEPT.DEPTNAME
方法二的实际结果跟预期结果有所不同,如下:
DEPTID DEPTNAME EMPNUMBER
1 开发 1
2 测试 0
3 需求 0
4 销售 0
要了解为何两个SQL语句的结果不同,就要明白SQL执行的顺序。如下:
1) 用笛卡尔乘积连接两张表;
2) 用ON条件过滤结果集;
3) LEFT、RIGHT、FULL条件起作用;
4) WHERE条件过滤结果集;
5) GROUP BY起作用。
下面分别列出两种方法中每一步执行的结果。
方法一
1) 用笛卡尔乘积连接两张表;
DEPTID DEPTNAME EMPID EMPNAME DEPTID
1 开发 1 张三 1
1 开发 2 李四 2
1 开发 3 王五 2
1 开发 4 赵六 2
1 开发 5 孙七 3
2 测试 1 张三 1
2 测试 2 李四 2
2 测试 3 王五 2
2 测试 4 赵六 2
2 测试 5 孙七 3
3 需求 1 张三 1
3 需求 2 李四 2
3 需求 3 王五 2
3 需求 4 赵六 2
3 需求 5 孙七 3
4 销售 1 张三 1
4 销售 2 李四 2
4 销售 3 王五 2
4 销售 4 赵六 2
4 销售 5 孙七 3
2) 用ON条件过滤结果集;
DEPTID DEPTNAME EMPID EMPNAME DEPTID
1 开发 1 张三 1
2 测试 2 李四 2
3 需求 5 孙七 3
3) LEFT、RIGHT、FULL条件起作用;
DEPTID DEPTNAME EMPID EMPNAME DEPTID
1 开发 1 张三 1
2 测试 2 李四 2
3 需求 5 孙七 3
4 销售 NULL NULL NULL
4) WHERE条件过滤结果集;
DEPTID DEPTNAME EMPID EMPNAME DEPTID
1 开发 1 张三 1
5) GROUP BY起作用。
DEPTID DEPTNAME EMPNUMBER
1 开发 1
方法二
1) 用笛卡尔乘积连接两张表;同方法一
2) 用ON条件过滤结果集;
DEPTID DEPTNAME EMPID EMPNAME DEPTID
1 开发 1 张三 1
3) LEFT、RIGHT、FULL条件起作用;
DEPTID DEPTNAME EMPID EMPNAME DEPTID
1 开发 1 张三 1
2 测试 NULL NULL NULL
3 需求 NULL NULL NULL
4 销售 NULL NULL NULL
4) WHERE条件过滤结果集;无WHERE过滤条件
5) GROUP BY起作用。
DEPTID DEPTNAME EMPNUMBER
1 开发 1
2 测试 0
3 需求 0
4 销售 0
结论
对于外连接,一定注意不要把连接条件和过滤条件混淆了。其实,即使对于内连接,把连接条件和过滤条件分开来,对于可读性而言也很有好处。总而言之,推荐大家在跨表查询时,使用标准SQL写法(JOIN…ON…),并且把连接条件和过滤条件严格分开来。
分享到:
相关推荐
left_join_on_and与left_join_on_where的区别
### SQL语句JOIN中ON和WHERE的区别 #### 引言 在SQL中,JOIN操作用于合并两个或多个表中的行。正确理解`ON`和`WHERE`子句的区别对于高效地编写查询至关重要。本文将详细解释这两者的不同,并通过具体的例子来加深...
对于LEFT JOIN,WHERE条件的过滤发生在最后,不满足条件的记录会被删除,但对于INNER JOIN,ON和WHERE的效果相同,因为它们都只会保留匹配的记录。 举例说明,假设我们有两个表: 表1(tab1): | tab1.id | tab1....
这里我们将深入探讨几种JOIN类型及其使用,以及ON和WHERE子句的区别。 1. INNER JOIN: INNER JOIN返回两个表中匹配的记录。这意味着如果某个记录在其中一个表中没有对应的匹配项,那么这个记录就不会出现在结果集中...
在SQL查询中,JOIN操作是连接两个或多个表格的关键字,用于从多个表格中合并数据。LEFT JOIN(在某些数据库中称为LEFT OUTER JOIN)是一种特殊的JOIN类型,它着重于从左表(即指定的第一个表格)返回所有行,即使在...
1. SELECT * FROM a LEFT JOIN b ON a.id = b.id WHERE a.id = 1 2. SELECT * FROM a LEFT JOIN b ON a.id = b.id AND a.id = 1 3. SELECT * FROM a LEFT JOIN b ON a.id = b.id AND b.id = 1 4. SELECT * FROM a ...
在PL/SQL(Oracle数据库的编程语言)中,JOIN语法尤其重要,因为它是处理复杂查询的基础。以下是PL/SQL中不同类型的JOIN及其特点的详细分析: 1. **左连接(LEFT JOIN)**: 左连接返回左表(Aa)的所有行,即使在...
### SQL中JOIN的使用详解 在SQL查询语言中,`JOIN`操作是非常重要的一个部分,它主要用于合并两个或多个表中的数据。通过不同的`JOIN`类型,我们可以灵活地获取所需的组合数据。本文将详细介绍五种主要的`JOIN`类型...
同样,在SQL语句6和7中,虽然使用了不同的语法(WHERE子句代替ON子句),但由于INNER JOIN的特性,它们产生的结果也是相同的,因为所有条件都在寻找匹配记录时被考虑。 WHERE子句通常用于过滤已经JOIN后的结果,而...
### SQL Server 中 DELETE 语句结合 INNER JOIN 的应用 #### 背景介绍 在数据库管理与维护过程中,经常会遇到需要删除表中的某些记录的情况。简单地使用 `DELETE` 语句可以删除单个表中的数据,但在多表关联的情况...
而on和where是用于指定连接条件和过滤结果集的关键字,在Left Join中它们的使用方法和时机对最终查询结果会产生重大影响。 在Left Join的语句中,on关键字用于指定连接条件,它定义了两张表之间如何关联,确保了...
当我们涉及到LEFT JOIN时,可能会遇到使用ON和WHERE子句的情况,两者虽然都可以用来指定条件,但在语义上有所区别。 首先,ON子句是在生成联接结果集(临时表)时应用的条件。无论ON条件是否为真,都会返回左表的...
SQL Join 语句详解 SQL Join 语句是数据库管理系统中最基本也是最重要的语句之一。它允许用户从多个表中检索数据,并将其组合成一个结果集。今天,我们将使用图形来解释 SQL Join 语句的各种类型。 INNER JOIN ...
### SQL语句中JOIN的用法详解 在SQL查询语言中,`JOIN`是一个非常重要的概念,它允许我们从两个或多个表中提取数据。通过使用不同类型的JOIN操作,我们可以根据表之间的关系来灵活地组织数据。下面我们将详细介绍几...
[t0].[Discontinued] FROM [dbo].[Products] AS [t0] LEFT OUTER JOIN [dbo].[Suppliers] AS [t1] ON [t1].[SupplierID] = [t0].[SupplierID] WHERE ([t1].[Country] = @p0) AND ([t0].[UnitsInStock] = @p1) -- @p0...
SELECT * FROM t_institution i RIGHT OUTER JOIN t_teller t ON i.inst_no = t.inst_no WHERE i.inst_no = "5801" 全外连接(Full Outer Join) 全外连接是将左、右两个表的全部行连接起来,例如: SELECT * ...
JOIN操作通常与ON子句一起使用来指定连接条件,而WHERE子句则用于过滤结果集。需要注意的是,ON条件和WHERE条件的区别:ON用于定义表之间的关联,而WHERE用于筛选满足特定条件的行。 8. **多表JOIN**: SQL允许...
在使用LEFT JOIN和RIGHT JOIN时,条件筛选可以使用ON和WHERE子句。它们之间的差异是很多人容易混淆的地方。ON子句是在连接操作中对连接条件进行指定,而WHERE子句通常用于对结果集进行过滤。由于这两者在查询的逻辑...
在SQL语言中,`LEFT JOIN` 和 `COUNT` 是两种非常重要的操作,它们在数据库查询中扮演着关键角色。在这个问题中,我们看到一个数据表 `TPL_WORD1`,它包含字段 `Wordid`(主键)、`idFuid`(上一级节点ID)和 `Name`...