大多数人一般写多表查询会这样写select * from tbA ,tbB 没有用到JOIN关键字,太Low了,官网标准建议是用JOIN明确表间的关系,下面具体来讲。
- 交叉联接 得到所连接表的所有组合 (笛卡儿集)cross join
- 内联接得到连接表的满足条件的记录组合inner join on
- 外联接(左、右)得到一个表的所有行,及其余表满 足连接条件的行 full | left | right outer join on
交叉联接
在这类联接的结果集内,两个表中每两个可能成对的行占一行。
但是如果在交叉联接中加入where 子句就相当与是内联接
例:
1
2
3
4
5
|
SELECT
title,
pub_name
FROM
titles
Cross JOIN
publishers
Where
titles.pub_id
=
publishers.pub_id
|
这就相当于我们一最开始的写法:SELECT title, pub_name FROM titles , publishers Where titles.pub_id = publishers.pub_id
执行过程:
内联接
仅显示两个联接表中的匹配行的联接。(这是查询设计器中的默认联接类型。)
例:
1
2
3
4
5
|
SELECT
title,
pub_name
FROM
titles
INNER JOIN
publishers
ON
titles.pub_id
=
publishers.pub_id
|
执行过程:
左向外联接
包括第一个命名表(”左”表,出现在 JOIN 子句的最左边)中的所有行。不包括右表中的不匹配行。
例:
1
2
3
4
5
|
SELECT
titles.title_id,titles.title,publishers.pub_name
FROM
titles
LEFT OUTER JOIN
publishers
ON
titles.pub_id
=
publishers.pub_id
|
右向外联接
包括第二个命名表(”右”表,出现在 JOIN 子句的最右边)中的所有行。不包括左表中的不匹配行。
例:
1
2
3
4
5
|
SELECT
titles.title_id,
titles.title,publishers.pub_name
FROM
titles
RIGHT OUTER JOIN
publishers
ON
titles.pub_id
=
publishers.pub_id
|
执行过程:
完整外部联接
包括所有联接表中的所有行,不论它们是否匹配。
例:
1
2
3
4
5
|
SELECT
titles.title_id,
titles.title,
publishers.pub_name
FROM
titles
FULL
OUTER
JOIN
publishers
ON
titles.pub_id
=
publishers.pub_id
|
练习:
此后用到的用例数据库是SQL2008里面的
用例数据库文件:链接:http://pan.baidu.com/s/1qW1QxA0 密码:dqxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
/*返回值2007年2月12日下过订单的客户,以及他们的订单。同时也返回在2007年2月12日没有下过订单的客户。
涉及到表:Sales.Customers表和Sales.Orders表。
期望的输出(按简略格式显示):
*/
custid
companyname
orderid
orderdate
---------
-- --------------- ----------- -----------------------
Customer
AHPOP
NULL
NULL
Customer
AHXHT
NULL
NULL
Customer
AZJED
NULL
NULL
Customer
BSVAR
NULL
NULL
Customer
CCFIZ
NULL
NULL
...
Customer
FVXPQ
NULL
NULL
Customer
GCJSG
NULL
NULL
Customer
GLLAG
NULL
NULL
Customer
GYBBY
NULL
NULL
Customer
HFBZG
NULL
NULL
Customer
HGVLZ
10444
2007
-02
-12
00:00:00.000
Customer
IAIJK
NULL
NULL
Customer
IBVRG
NULL
NULL
Customer
IRRVL
NULL
NULL
Customer
JMIKW
NULL
NULL
Customer
JUWXK
NULL
NULL
...
Customer
KIDPX
NULL
NULL
Customer
KSLQF
NULL
NULL
Customer
KZQZT
NULL
NULL
Customer
LCOUJ
NULL
NULL
Customer
LCYBZ
NULL
NULL
Customer
LHANT
10443
2007
-02
-12
00:00:00.000
Customer
LJUCA
NULL
NULL
Customer
LOLJO
NULL
NULL
Customer
LVJSO
NULL
NULL
Customer
LWGMD
NULL
NULL
Customer
MDLWA
NULL
NULL
...
|
参考SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
--answer:
select
c.custid,c.companyname,o.orderid,o.orderdate
from
Sales.Customers
as
c
left join
Sales.Orders
as
o
on
c.custid
=o.custid
and
o.orderdate=
'2007-2-12'
/*
1.将表Sales.Customers别名为c和表Sales.Orders别名为o应用ON筛选器以custid和o.orderdate='2007-2-12'为条件左外连接,生成虚拟表VT1,
2.添加外部行,外部行中非保留表中的属性被赋值为NULL,生成虚拟表VT2
3.处理select列表,从虚拟表VT2中查找出c.custid,c.companyname,o.orderid,o.orderdate生成虚拟表VT3
*/
注意
and
o.orderdate=
'2007-2-12'
改成
where
o.orderdate=
'2007-2-12',请注意这个结果又是什么呢?
|
1
2
3
4
5
6
7
8
|
/*返回没有下过订单的客户。
涉及的表:Sales.Customers表和Sales.Orders表。
期望的输出:
*/
custid
companyname
---------
-- ---------------
Customer
DTDMN
Customer
WVAXS
|
参考SQL:
1
2
3
4
5
6
7
8
9
10
11
12
|
--answer:
select
c.custid,c.companyname
from
Sales.Customers
as
c
left join
Sales.Orders
as
o
on
c.custid
=o.custid
where
o.orderid
is
null
/*
1.将表Sales.Customers别名为c和表Sales.Orders别名为o应用ON筛选器以custid为条件左外连接,生成虚拟表VT1,
2.添加外部行,外部行中非保留表中的属性被赋值为NULL,生成虚拟表VT2
3.应用where筛选器选出o.orderid 为 null的数据生成虚拟表VT3
4.处理select列表,查找出c.custid,c.companyname生成虚拟表VT4
*/
|