SQL子查询的运算

时间:2023-01-31 22:32:30

子查询是嵌套在一个select语句中的另一个select语句。当需要从一个表中检索信息,检索条件值又是来自该表本身的内部数据时,子查询非常有用。
子查询可以嵌入以下SQL子句中:where子句、having子句和from子句。

例:查询工资比编号为7566雇员工资高的雇员姓名。
SQL>select ename
from   emp
where sal>
      (select sal
        from emp
        where empno=7566)
order by ename;

说明:
(1)子查询要用括号括起来;
(2)将子查询放在比较运算符的右边;
(3)不要在子查询中使用order by子句,select语句中只能有一个order by子句,并且它只能是主select语句的最后一个子句。

1、单行子查询
内部select语句只返回一行结果的查询(单列)。主查询的where子句使用单行子查询返回结果要采用单行比较运算符(=、>、>=、<、<=、<>)。

1.1 Where子句中使用单行子查询

例:显示和雇员scott同部门的雇员姓名、工资和部门编号。
SQL>select ename,sal,deptno
from   emp
where deptno=
      (select deptno
        from emp
        where ename='SCOTT');

ENAME            SAL DEPTNO
---------- --------- ------
SMITH         800.00     20
JONES        2975.00     20
SCOTT        3000.00     20
ADAMS        1100.00     20
FORD         3000.00     20

练习:显示和雇员SCOTT从事相同工作,并且工资大于JAMES的雇员姓名、工作和工资。
SQL>select ename,job,sal
from   emp
where job=
      (select job from emp where ename='SCOTT')
and   sal>
      (select sal from emp where ename='JAMES');

ENAME      JOB             SAL
---------- --------- ---------
SCOTT      ANALYST     3000.00
FORD       ANALYST     3000.00

1.2单行子查询中使用组函数

例:显示工资最低的雇员姓名、工作和工资。
SQL> select ename,job,sal
from emp
where sal=(select min(sal) from emp);

ENAME      JOB             SAL
---------- --------- ---------
SMITH      CLERK        800.00

练习1:显示工资最高的雇员姓名、工作和工资。
练习2:显示工资高于平均工资的雇员姓名、工作、工资和工资等级。
SQL>select e.ename as 姓名,
       e.job as 工作,
       e.sal as 工资,
       s.grade as 工资等级
from emp e,salgrade s
where e.sal>(select avg(sal) from emp)           
and e.sal between s.losal and s.hisal;

姓名       工作             工资       工资等级
---------- --------- --------- ----------
JONES      MANAGER     2975.00          4
BLAKE      MANAGER     2850.00          4
CLARK      MANAGER     2450.00          4
SCOTT      ANALYST     3000.00          4
KING       PRESIDENT   5000.00          5
FORD       ANALYST     3000.00          4

思考?
e.sal>(select avg(sal) from emp)和e.sal between s.losal and s.hisal顺序对调查询效率上有何差异?为什么?

1.3 having子句中使用单行子查询

例:显示部门内最低工资比20部门最低工资要高的部门的编号及部门内最低工资。
(1)按部门显示部门编号、部门最低工资
SQL>select deptno as 部门编号,
       min(sal) as 最低工资
from emp
group by deptno;

(2)查询20部门最低工资
select min(sal) from emp where deptno=20

(3)使用having子句把(2)作为(1)的子查询
SQL>select deptno as 部门编号,
       min(sal) as 最低工资
from emp
group by deptno
having min(sal)>(select min(sal)
                 from emp
                 where deptno=20);

    部门编号  最低工资
--------  ----------
      30        950
  10       1300


练习:查询平均工资最低的工种名称及其平均工资。
(1)按工种查询平均工资
SQL>select job,avg(sal) from emp group by job;

(2)按工种查询最低平均工资
SQL>select min(avg(sal)) from emp group by job;

(3)使用having子句把(2)作为(1)子查询
SQL>select job,avg(sal)
from emp
group by job
having avg(sal)=(select min(avg(sal))
                 from emp
                 group by job);

JOB           AVG(SAL)
---------    ----------
CLERK         1037.5


问题思考:
(1)当单行子查询返回的结果为null时,主查询是否正确?

例:查询和SMITH从事相同工作的雇员姓名和工作
select ename,job
from emp
where job=(select job
           from emp
           where ename='SMITHS');
如果SMITH误拼写成SMITHS则返回结果为null。

(2)子查询中使用group by子句,主查询中是否可以使用单行比较符?

例:下面的SQL语句能正确执行吗?
SQL>select ename,job
from emp
where sal=(select min(sal)
           from emp
           group by deptno)

ORA-01427: 单行子查询返回多个行

2、多行子查询
内部select语句返回多行结果,主查询的where子句使用多行子查询返回的结果要采用多行比较运算符,多行比较运算符可以和一个或多个值进行比较。
多行运算比较符:in、any、all

2.1 使用in运算符的多行子查询
In运算符将等于列表中的任意一项。

例1:查询有下属的雇员姓名、工作、工资和部门号。
SQL>select ename,job,sal,deptno
from emp
where empno in (select mgr from emp);

ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
JONES      MANAGER     2975.00     20
BLAKE      MANAGER     2850.00     30
CLARK      MANAGER     1500.00     10
SCOTT      ANALYST     3000.00     20
KING       PRESIDENT   5000.00     10
FORD       ANALYST     3000.00     20

思考?
如果要查询没有下属的雇员姓名、工作、工资和部门号,如下的SQL语句是否可以获得预期的结果?如果不能,应如何修改?
SQL>select ename,job,sal,deptno
from emp
where empno not in (select mgr from emp);

解答:
为把问题说清楚,先看一下子查询的执行结果:
SQL> select ename,mgr from emp;

ENAME        MGR
---------- -----
SMITH       7902
ALLEN       7698
WARD        7698
JONES       7839
MARTIN      7698
BLAKE       7839
CLARK       7839
SCOTT       7566
KING      
TURNER      7698
ADAMS       7788
JAMES       7698
FORD        7566
MILLER      7782

子查询返回的结果中有一个mgr是空值,not in运算符将会用主查询条件(empno)与子查询中的每个结果(mgr)进行逻辑非的比较。因为子查询返回结果中有条空值,任何条件和空值比较都是空值。因此只要空值成为子查询的一部分,就不能用not in运算符。

SQL语句更正如下:
SQL>select ename,job,sal,deptno
from emp
where empno not in (select nvl(mgr,-1) from emp);


SQL>select ename,job,sal,deptno
from emp
where empno not in (select mgr from emp where mgr is not null);

例2:查询各部门中工资最低的员工姓名、工作、工资和部门号
SQL>select ename,job,sal,deptno
from emp
where sal in (select min(sal)
          from emp
          group by deptno);

ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
JAMES      CLERK        950.00     30
SMITH      CLERK        800.00     20
MILLER     CLERK       1300.00     10

练习1:查询部门中工资最高的雇员姓名、工作、工资和部门号。
SQL>select ename,job,sal,deptno
from emp
where sal in (select max(sal)
              from emp
          group by deptno);

练习2:查询与销售部门(SALES)工作相同的其它部门雇员姓名、工作、工资和部门名称。
SQL>select e.ename,e.job,e.sal,d.dname
from emp e,dept d
where e.deptno=d.deptno
      and d.dname<>'SALES'
      and job in (select distinct e.job
              from emp e,dept d
              where e.deptno=d.deptno and d.dname='SALES');

ENAME      JOB             SAL DNAME
---------- --------- --------- --------------
CLARK      MANAGER     2450.00 ACCOUNTING
JONES      MANAGER     2975.00 RESEARCH
MILLER     CLERK       1300.00 ACCOUNTING
ADAMS      CLERK       1100.00 RESEARCH
SMITH      CLERK        800.00 RESEARCH


2.2 使用any运算符的多行子查询
Any运算符将和内部查询返回的结果逐个比较,与单行操作符配合使用。
<any:表示比子查询返回结果中的最大值小;
=any:表示可以是子查询返回结果中的任意一个值;
>any:表示比子查询返回结果中的最小值大。

例1:查询工资低于某个文员(CLERK)雇员工资,但不从事文员工作的雇员编号、姓名、工种和工资。
SQL>select empno,ename,job,sal
from emp
where sal<any
          (select sal
           from emp
           where job='CLERK')
    and job<>'CLERK';

EMPNO ENAME      JOB             SAL
----- ---------- --------- ---------
7521 WARD       SALESMAN    1250.00
7654 MARTIN     SALESMAN    1250.00

例2:查询工资高于某个文员(CLERK)雇员工资,但不从事文员工作的雇员编号、姓名、工种和工资。
SQL>select empno,ename,job,sal
from emp
where sal>any
          (select sal
           from emp
           where job='CLERK')
    and job<>'CLERK';

EMPNO ENAME      JOB             SAL
----- ---------- --------- ---------
7839 KING       PRESIDENT   5000.00
7788 SCOTT      ANALYST     3000.00
7902 FORD       ANALYST     3000.00
7566 JONES      MANAGER     2975.00
7698 BLAKE      MANAGER     2850.00
7782 CLARK      MANAGER     2450.00
7499 ALLEN      SALESMAN    1600.00
7844 TURNER     SALESMAN    1500.00
7521 WARD       SALESMAN    1250.00
7654 MARTIN     SALESMAN    1250.00

练习1:查询工资高于部门编号是30的部门内某个雇员工资,但不在该部门工作的雇员姓名、工种、工资和部门编号。
SQL>select ename,job,sal,deptno
from emp
where sal>any
          (select sal
           from emp
           where deptno=30)
      and deptno<>30;

练习2:查询工资低于部门名称是SALES的部门内某个雇员工资,但不在该部门工作的雇员姓名、工种、工资、部门编号和部门名称。
SQL>select e.ename,e.job,e.sal,d.deptno,d.dname
from emp e,dept d
where e.deptno=d.deptno
      and d.dname<>'SALES'
      and sal<any
             (select distinct e.sal
              from emp e,dept d
              where e.deptno=d.deptno and d.dname='SALES');

ENAME      JOB             SAL DEPTNO DNAME
---------- --------- --------- ------ --------------
SMITH      CLERK        800.00     20 RESEARCH
ADAMS      CLERK       1100.00     20 RESEARCH
MILLER     CLERK       1300.00     10 ACCOUNTING
CLARK      MANAGER     2450.00     10 ACCOUNTING

2.3 使用all运算符的多行子查询
All运算符将和内部查询返回的每个结果比较。
>all:比最大的大;
<all:比最小的小。

例1:查询高于所有部门平均工资的雇员姓名、工作、工资和部门编号。
SQL>select ename,job,sal,deptno
from emp
where sal>all (select avg(sal)
               from emp
               group by deptno);

ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
JONES      MANAGER     2975.00     20
SCOTT      ANALYST     3000.00     20
KING       PRESIDENT   5000.00     10
FORD       ANALYST     3000.00     20

例2:查询低于所有部门平均工资的雇员姓名、工作、工资和部门编号。
SQL>select ename,job,sal,deptno
from emp
where sal<all (select avg(sal)
               from emp
               group by deptno);

ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
SMITH      CLERK        800.00     20
WARD       SALESMAN    1250.00     30
MARTIN     SALESMAN    1250.00     30
TURNER     SALESMAN    1500.00     30
ADAMS      CLERK       1100.00     20
JAMES      CLERK        950.00     30
MILLER     CLERK       1300.00     10

练习1:查询工资高于部门编号为30的部门内所有员工工资的雇员姓名、工作、工资和部门编号
select ename,job,sal,deptno
from emp
where sal>all (select sal from emp where deptno=30);

ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
JONES      MANAGER     2975.00     20
SCOTT      ANALYST     3000.00     20
KING       PRESIDENT   5000.00     10
FORD       ANALYST     3000.00     20

练习2:查询工资等级为4的雇员姓名、工作、工资、部门编号和工资等级,同时满足该雇员工资高于部门编号为30的部门内所有员工工资。
SQL>select e.ename,e.job,e.sal,e.deptno,s.grade
from emp e,salgrade s
where s.grade=4
and e.sal between s.losal and s.hisal
and e.sal>all (select sal from emp where deptno=30);

ENAME      JOB             SAL DEPTNO      GRADE
---------- --------- --------- ------ ----------
JONES      MANAGER     2975.00     20          4
SCOTT      ANALYST     3000.00     20          4
FORD       ANALYST     3000.00     20          4


3、多列子查询
多列子查询返回多列结果的内部select语句,多列子查询中的列比较有成对比较与不成对比较两种方法。
多列子查询分为成对比较多列子查询和非成对比较多列子查询。

对emp表的数据进行修改:
SQL> update emp set sal=1600,comm=300 where ename='SMITH';
SQL> update emp set sal=1500,comm=300 where ename='CLARK';

3.1成对比较多列子查询
例:查询与部门编号为30的部门中任意一个雇员的工资和奖金完全相同的雇员姓名、工资、奖金、部门编号,满足该雇员不是来自30号部门。
(1)查询30部门内雇员工资和奖金
SQL>select sal,nvl(comm,-1) from emp where deptno=30;     

SAL NVL(COMM,-1)
--------- ------------
  1600.00          300
  1250.00          500
  1250.00         1400
  2850.00           -1
  1500.00            0
   950.00           -1

(2)查询非30部门内雇员姓名、工资、奖金和部门编号
SQL>select ename,sal,nvl(comm,-1),deptno from emp where deptno<>30;

ENAME            SAL NVL(COMM,-1) DEPTNO
---------- --------- ------------ ------
SMITH        1600.00          300     20
JONES        2975.00           -1     20
CLARK        1500.00          300     10
SCOTT        3000.00           -1     20
KING         5000.00           -1     10
ADAMS        1100.00           -1     20
FORD         3000.00           -1     20
MILLER       1300.00           -1     10

(3)把(1)作为(2)的子查询
查询(2)中与查询(1)中工资和奖金完全匹配的只有SMITH一个雇员,下面找出该员工。
SQL>select ename,sal,nvl(comm,-1),deptno
from emp
where deptno<>30
      and (sal,nvl(comm,-1))  in (select sal,nvl(comm,-1)
                                  from emp
                                  where deptno=30);

ENAME            SAL NVL(COMM,-1) DEPTNO
---------- --------- ------------ ------
SMITH        1600.00          300     20

练习1:创建一查询,显示能获得与SCOTT一样工资和奖金的其他雇员的姓名、受雇日期和工资。

练习2:查询各部门中工资等级最高的雇员姓名、工作、工资、工资等级和部门号。
select e.ename,e.job,e.sal,s.grade,e.deptno
from emp e,salgrade s
where e.sal between s.losal and s.hisal
and (s.grade,e.deptno)  in (
                           select  max(s.grade),e.deptno
                           from emp e,salgrade s
                           where e.sal between s.losal and s.hisal
                           group by e.deptno)
order by e.deptno;

ENAME      JOB             SAL      GRADE DEPTNO
---------- --------- --------- ---------- ------
KING       PRESIDENT   5000.00          5     10
FORD       ANALYST     3000.00          4     20
JONES      MANAGER     2975.00          4     20
SCOTT      ANALYST     3000.00          4     20
BLAKE      MANAGER     2850.00          4     30

练习3:查询各部门中工资等级最高的雇员姓名、工作、工资、工资等级和部门名称。
select e.ename,e.job,e.sal,s.grade,d.dname
from emp e,salgrade s,dept d
where e.sal between s.losal and s.hisal
      and e.deptno=d.deptno
      and (s.grade,e.deptno)  in (select  max(s.grade),e.deptno
                                 from emp e,salgrade s
                                 where e.sal between s.losal and s.hisal
                                 group by e.deptno)
order by e.deptno;

ENAME      JOB             SAL      GRADE DNAME
---------- --------- --------- ---------- --------------
KING       PRESIDENT   5000.00          5 ACCOUNTING
FORD       ANALYST     3000.00          4 RESEARCH
JONES      MANAGER     2975.00          4 RESEARCH
SCOTT      ANALYST     3000.00          4 RESEARCH
BLAKE      MANAGER     2850.00          4 SALES

3.2非成对比较多列子查询
例:查询工资与30部门中任意一个雇员的工资相等,同时奖金也与30部门中任意一个雇员奖金相等的雇员姓名、工资、奖金、部门编号,但该雇员不是来自30号部门。

SQL>select ename,sal,nvl(comm,-1),deptno
from emp
where deptno<>30
      and sal in (select sal
                  from emp
                  where deptno=30)
      and nvl(comm,-1) in (select nvl(comm,-1)
                           from emp
                           where deptno=30);

ENAME            SAL NVL(COMM,-1) DEPTNO
---------- --------- ------------ ------
SMITH        1600.00          300     20
CLARK        1500.00          300     10


练习1:查询工资与销售部门(SALES)中任意一个雇员的工资相等,同时奖金也与该部门中任意一个雇员奖金相等的雇员姓名、工资、奖金、部门编号、部门名称,但该雇员不是来自销售部门。
SQL>select e.ename,e.sal,nvl(e.comm,-1),d.deptno,d.dname
from emp e,dept d
where (e.deptno=d.deptno) and d.dname<>'SALES'
      and e.sal in
(select e.sal
                 from emp e,dept d
                 where (e.deptno=d.deptno) and d.dname='SALES')
      and nvl(e.comm,-1) in
(select nvl(e.comm,-1)
                         from emp e,dept d
                         where (e.deptno=d.deptno) and d.dname='SALES');

ENAME            SAL NVL(E.COMM,-1) DEPTNO DNAME
---------- --------- -------------- ------ --------------
CLARK        1500.00            300     10 ACCOUNTING
SMITH        1600.00            300     20 RESEARCH

练习2:显示与工作在DALLAS的雇员的工资及奖金同时匹配的雇员姓名、部门名称及工资。


3、相关子查询(exists)
相关子查询指需要引用主查询列表的子查询语句,通过exists谓词实现。对主查询的每条记录都需执行一次子查询来测试是否匹配。若子查询返回结果非空,则主查询的where子句返回值为true,否则返回值为false。

例:查询在纽约(NEW YORK)工作的雇员姓名、工种、工资和奖金。
SQL>select ename,job,sal,comm
from emp
where exists (select *
              from dept
              where emp.deptno=deptno and loc='NEW YORK');

ENAME      JOB             SAL      COMM
---------- --------- --------- ---------
CLARK      MANAGER     1500.00    300.00
KING       PRESIDENT   5000.00
MILLER     CLERK       1300.00


练习:查询工资等级为4的雇员姓名、工种和工资
SQL>select ename,job,sal
from emp
where exists (select *
              from  salgrade
              where emp.sal between losal and hisal
                and grade=4);

ENAME      JOB             SAL
---------- --------- ---------
FORD       ANALYST     3000.00
SCOTT      ANALYST     3000.00
JONES      MANAGER     2975.00
BLAKE      MANAGER     2850.00


4、from子句中使用子查询
在from子句中使用子查询时,必须给子查询指定别名。

例:显示工资高于部门平均工资的雇员姓名、工作、工资和部门号。
SQL>select ename,job,sal,emp.deptno
from emp, (select deptno,avg(sal) avgsal
           from  emp
           group by deptno)s
where emp.deptno=s.deptno and sal>s.avgsal;

ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
ALLEN      SALESMAN    1600.00     30
JONES      MANAGER     2975.00     20
BLAKE      MANAGER     2850.00     30
SCOTT      ANALYST     3000.00     20
KING       PRESIDENT   5000.00     10
FORD       ANALYST     3000.00     20

练习:查询各部门中工资等级最高的雇员姓名、工作、工资、工资等级和部门号。
方法一、from子句中使用一个子查询
select e.ename,e.job,e.sal,s.grade,e.deptno
from emp e,
     salgrade s,
     (select max(s.grade) grade,e.deptno
      from emp e,salgrade s
      where e.sal between s.losal and s.hisal
      group by e.deptno)q
where  e.sal between s.losal and s.hisal
       and e.deptno=q.deptno and s.grade=q.grade
order by e.deptno;

ENAME      JOB             SAL      GRADE DEPTNO
---------- --------- --------- ---------- ------
KING       PRESIDENT   5000.00          5     10
JONES      MANAGER     2975.00          4     20
SCOTT      ANALYST     3000.00          4     20
FORD       ANALYST     3000.00          4     20
BLAKE      MANAGER     2850.00          4     30

方法二、from子句中使用两个子查询
select p.ename,p.job,p.sal,p.grade,p.deptno
from  (
         select e.ename,e.job,e.sal,s.grade,e.deptno
         from emp e,salgrade s
         where e.sal between s.losal and s.hisal)p,
      (
         select max(s.grade) grade,e.deptno
         from emp e,salgrade s
         where e.sal between s.losal and s.hisal
         group by e.deptno)q
where p.deptno=q.deptno and p.grade=q.grade
order by p.deptno;

---------------------------------------------------------------------

left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
inner join(等值连接) 只返回两个表中联结字段相等的行

举例如下:
--------------------------------------------
表A记录如下:
aID     aNum
1     a20050111
2     a20050112
3     a20050113
4     a20050114
5     a20050115

表B记录如下:
bID     bName
1     2006032401
2     2006032402
3     2006032403
4     2006032404
8     2006032408

--------------------------------------------
1.left join
sql语句如下:
select * from A
left join B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
5     a20050115    NULL     NULL

(所影响的行数为 5 行)
结果说明:
left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.
换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).
B表记录不足的地方均为NULL.
--------------------------------------------
2.right join
sql语句如下:
select * from A
right join B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
NULL     NULL     8     2006032408

(所影响的行数为 5 行)
结果说明:
仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.
--------------------------------------------
3.inner join
sql语句如下:
select * from A
innerjoin B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404

结果说明:
很明显,这里只显示出了 A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.
--------------------------------------------
注:
LEFT JOIN操作用于在任何的 FROM 子句中,组合来源表的记录。使用 LEFT JOIN 运算来创建一个左边外部联接。左边外部联接将包含了从第一个(左边)开始的两个表中的全部记录,即使在第二个(右边)表中并没有相符值的记录。

语法:FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2

说明:table1, table2参数用于指定要将记录组合的表的名称。
field1, field2参数指定被联接的字段的名称。且这些字段必须有相同的数据类型及包含相同类型的数据,但它们不需要有相同的名称。
compopr参数指定关系比较运算符:"=", "<", ">", "<=", ">=" 或 "<>"。
如果在INNER JOIN操作中要联接包含Memo 数据类型或 OLE Object 数据类型数据的字段,将会发生错误.

sql语句中left join、inner join中的on与where的区别

table a(id, type):

id     type

----------------------------------

1      1       

2      1        

3      2        

table b(id, class):

id    class

---------------------------------

1      1

2      2

sql语句1:select a.*, b.* from a left join b on a.id = b.id and a.type = 1;

sql语句2:select a.*, b.* from a left join b on a.id = b.id where a.type = 1;

sql语句3:select a.*, b.* from a left join b on a.id = b.id and b.class = 1;

sql语句1的执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2

3        2             

sql语句2的执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2

sql语句3的执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1          

3        2          

由sql语句1可见,left join 中左表的全部记录将全部被查询显示,on 后面的条件对它不起作用,除非再后面再加上where来进行筛选,这就是sql语句2了;由sql语句3可见,on后面的条件中,右表的限制条件将会起作用。

**********************************************************************************

sql语句4:select a.*, b.* from a inner join b on a.id = b.id and a.type = 1;

sql语句5:select a.*, b.* from a inner join b on a.id = b.id where a.type = 1;

sql语句6:select a.*, b.* from a, b where a.id = b.id and a.type = 1;

sql语句7:select a.*, b.* from a, b where a.type = 1 and a.id = b.id;

这四条语句的执行结果一样,如下:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2

由此可见,inner join 中on后面的限制条件将全部起作用,这与where的执行结果是一样的。另外,where语句与inner join确实能得到相同的结果,只是效率不同(这个我没有测试过,不过我相信这个结论)。