MSSQL中join的用法詳解

join 语句有三种,inner join, left outer join 和 right outer join 都可以简写,分别为join,left join,right join。

join语句可以用来组合两个表中的记录,只要在公共字段之中有相符的值即可,该语句联合两个表查询得到的结果是可以添加新的数据,可以把它看成将两个具有相关内容的表联接在一起新生成的表,而一般的select 语句没有这个功能。

1)      内连接,inner join ... on
    语句格式:
    FROM (((表1 INNER JOIN 表2 ON 表1.字段号=表2.字段号) INNER JOIN 表3 ON 表1.字段号=表3.字段号) INNER JOIN 表4 ON Member.字段号=表4.字段号) INNER JOIN 表X ON Member.字段号=表X.字段号

     例子:

    SELECT *

    FROM (((Member INNER JOIN MemberSort ON Member.MemberSort=MemberSort.MemberSort) INNER JOIN MemberLevel ON Member.MemberLevel=MemberLevel.MemberLevel) INNER JOIN MemberIdentity ON Member.MemberIdentity=MemberIdentity.MemberIdentity) INNER JOIN Wedlock ON Member.Wedlock=Wedlock.Wedlock

    ORDER BY MemberDate DESC

     内连接的功能是,把两个表相关联的记录列出来,必须是相关联的记录。

2)      左外连接,left outer join ... on

    语句格式:

      FROM [表名1] LEFT JOIN [表名2]

      ON [表名1.字段A] 〈关系运算符〉[表名2.字段B]

    其实LEFT JOIN 的功能就是将LEFT左边的表名1中的所有记录全部保留,而将右边的表名2中的字段B与表名1.字段A相对应的记录显示出来(当使用SELECT * 时)。而RIGHT JOIN 和LEFT JOIN 相反。

     外连接的功能是,把LEFT左边的表中的所有记录保留,而右边表只保留相关联的记录,也就是先执行一次INNER JOIN,然后把LEFT左边的表中的与右边表没有任何关联的记录也保留,而右边表的字段为null.

3)      右外连接,right outer join ... on

    与 left join左右相反。

4)      全连接,full join ... on(不常使用,只能用于outer)

     功能结合了以上三种联军,先执行一次inner join,然后把两个表的多余字段都保留,但连接的对应字段为null.

如果想将几个表联接起来,在JOIN操作中我们可以进行嵌套操作,有三个表:表1、表2、表3,现在将三个表联接起来:

      FROM (表1 INNER JOIN 表2 ON 表1.序号=表2.序号)

       INNER JOIN 表3 ON 表1.序号=表3.序号


===使用範例==================


在数据库中, 我们常会碰到的情形: 所需的资料并不是放在同一个资料表中, 在这个时候, 你就要用到 Join
当然 Join 如何将不同的数据库的资料结合, 还要看你如何使用它, 一共有四种不同的 Join 的方式, 在这篇文章中我们将为你介绍 Inner Join 及 Outer Join 以及其应用

Inner Join
Inner Join 应该是最常用的 Join 方式, 它只会反回符合 Join 规则的纪录, 还是先来看看语法
Select <要选择的字段> From <主要资料表>
<Join 方式> <次要资料表> [On <Join 规则>]
现在我们利用 MS SQL 内建的北风数据库来实际练习一下! 想多了解 MS SQL 的内建数据库, 你可以看看 SQL Server 的内建数据库 这篇文章
请打开 QA (Query Analyzer), 为了使用北风数据库, 请先执行 Use Northwind, 然后执行
Select ProductId, ProductName, SupplierId From Products
从 Products 产品资料表中取出三个字段, 分别是产品代码, 产品名称, 供货商代码, 但查询出来的结果保证让你的老板很不满意, 因为供货商代码对于人类实在是无虾米意义, 这个时候 Join 就可以帮上忙了, 藉由 Join Suppliers 这个资料表我们便可以查询到供货商名称
Select ProductId, ProductName, Suppliers.SupplierId From Products Inner Join Suppliers on Products.Suppliers = Suppliers.SupplierId
这款的查询结果是不是卡清楚呢! Inner Join 的主要精神就是 exclusive , 叫它做排他性吧! 就是讲 Join 规则不相符的资料就会被排除掉, 譬如讲在 Product 中有一项产品的供货商代码 (SupplierId), 没有出现在 Suppliers 资料表中, 那么这笔记录便会被排除掉

Outer Join
这款的 Join 方式是一般人比较少用到的, 甚至有些 SQL 的管理者也从未用过, 这真是一件悲哀的代志, 因为善用 Outer Join 是可以简化一些查询的工作的, 先来看看 Outer Join 的语法
Select <要查询的字段> From <Left 资料表>
<Left | Right> [Outer] Join <Right 资料表> On <Join 规则>
语法中的 Outer 是可以省略的, 例如你可以用 Left Join 或是 Right Join, 在本质上, Outer Join 是 inclusive, 叫它做包容性吧! 不同于 Inner Join 的排他性, 因此在 Left Outer Join 的查询结果会包含所有 Left 资料表的资料, 颠倒过来讲, Right Outer Join 的查询就会包含所有 Right 资料表的资料, 接下来我们还是来做些实际操作, 仍然是使用北风数据库, 但要先做一些小小的修改, 才能达到我们要的结果
首先要拿掉 Products 资料表的 Foreign Key, 否则没有法度在 Products 资料表新增一笔 SupplierId 没有对映到 Suppliers 资料表的纪录, 要知影一个资料表的 Constraint 你可以执行 SQL 内建的 sp_helpconstraint , 在 QA 执行
sp_helpconstraint Products
接下来删除 FK_Products_Suppliers 这个 Foreign Key
Alter Table Products
Drop Constraint FK_Products_Suppliers
再来新增一笔纪录于 Products 资料表, SupplierId 使用 50 是因为它并没有对映到 Suppliers 资料表中的记录
Insert Into Products (ProductName,SupplierId,CategoryId) values ('Test Product','50','1')
现在我们再执行头前的查询, 只是将 Inner Join 改为 Left Outer Join
Select ProductId, ProductName, Suppliers.SupplierId From Products Left Outer Join Suppliers on Products.Suppliers = Suppliers.SupplierId
比较一下两种 Join 方式的查询结果, 你应该就会知影其中的差别!
再来看看 Right Outer Join, 请新增下底这笔记录
Insert Into Suppliers (CompanyName) values ('LearnASP')
现在请使用 Right Out Join 来作查询, 比较看看查询的结果和 Inner Join 有什么不同!
寻找不相符纪录
这里我们来看看如何使用 Out Join 来找不相符纪录, 可能是有子纪录却没有父纪录或是颠倒过来
Select Suppliers.CompanyName From Products Right Join Suppliers On Products.SupplierId = ppliers.SupplierId Where Products.SupplierId is Null
执行结果你会找到一笔资料为 LearnASP, 该笔供货商资料存在, 但基本上已经没有产品是来自这个供货商, 想象一下如果不用 Outer Join 你要怎么以一个 SQL 指令完成同一查询结果! 知道 Outer Join 的好用了吧! 再执行
Select Products.ProductName From Products Left Join Suppliers On Products.SupplierId = Suppliers.SupplierId Where Suppliers.SupplierId is Null
这个查询结果你会发现 Test Product 这项产品竟然找不到供货商的资料!

===SQL 中inner join、(left,right,full)outer join的用法=======================
來源:http://www.cnblogs.com/javacoffee/articles/1286723.html

使用关系代数合并数据
1 关系代数
合并数据集合的理论基础是关系代数,它是由E.F.Codd于1970年提出的。
在关系代数的形式化语言中:
        用表、或者数据集合表示关系或者实体。
        用行表示元组。
        用列表示属性。
关系代数包含以下8个关系运算符
        选取――返回满足指定条件的行。
        投影――从数据集合中返回指定的列。
        笛卡尔积――是关系的乘法,它将分别来自两个数据集合中的行以所有可能的方式进行组合。
        并――关系的加法和减法,它可以在行的方向上合并两个表中的数据,就像把一个表垒在另一个表之上一样。
        交――返回两个数据集合所共有的行。
        差――返回只属于一个数据集合的行。
        连接――在水平方向上合并两个表,其方法是:将两个表中在共同数据项上相互匹配的那些行合并起来。
        除――返回两个数据集之间的精确匹配。
此外,作为一种实现现代关系代数运算的方法,SQL还提供了:
        子查询――类似于连接,但更灵活;在外部查询中,方式可以使用表达式、列表或者数据集合的地方都可以使用子查询的结果。
本章将主要讲述多种类型的连接、简单的和相关的子查询、几种类型的并、关系除以及其他的内容。
2 使用连接
2.1 连接类型
在关系代数中,连接运算是由一个笛卡尔积运算和一个选取运算构成的。首先用笛卡尔积完成对两个数据集合的乘运算,然后对生成的结果集合进行选取运算,确保只把分别来自两个数据集合并且具有重叠部分的行合并在一起。连接的全部意义在于在水平方向上合并两个数据集合(通常是表),并产生一个新的结果集合,其方法是将一个数据源中的行于另一个数据源中和它匹配的行组合成一个新元组。
SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。
连接类型        定义
内连接        只连接匹配的行
左外连接        包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
右外连接        包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
全外连接        包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。
(H)(theta)连接        使用等值以外的条件来匹配左、右两个表中的行
交叉连接        生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配
在INFORMIX中连接表的查询
如果FROM子句指定了多于一个表引用,则查询会连接来自多个表的行。连接条件指定各列之间(每个表至少一列)进行连接的关系。因为正在比较连接条件中的列,所以它们必须具有一致的数据类型。
SELECT语句的FROM子句可以指定以下几种类型的连接
FROM子句关键字        相应的结果集
CROSS JOIN        笛卡尔乘积(所有可能的行对)
INNER JOIN        仅对满足连接条件的CROSS中的列
LEFT OUTER JOIN        一个表满足条件的行,和另一个表的所有行
RIGHT OUTER JOIN        与LEFT相同,但两个表的角色互换
FULL OUTER JOIN        LEFT OUTER 和 RIGHT OUTER中所有行的超集

2.2 内连接(Inner Join)
内连接是最常见的一种连接,它页被称为普通连接,而E.FCodd最早称之为自然连接。
下面是ANSI SQL-92标准
select *
from  t_institution i
inner join t_teller t
on i.inst_no = t.inst_no
where i.inst_no = "5801"
其中inner可以省略。
等价于早期的连接语法
select *
from t_institution i, t_teller t
where i.inst_no = t.inst_no
and i.inst_no = "5801"

2.3 外连接
2.3.1        左外连接(Left Outer Jion)
select *
from  t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
其中outer可以省略。
2.3.2        右外连接(Rigt Outer Jion)
select *
from  t_institution i
right outer join t_teller t
on i.inst_no = t.inst_no
2.3.3        全外连接(Full Outer)
全外连接返回参与连接的两个数据集合中的全部数据,无论它们是否具有与之相匹配的行。在功能上,它等价于对这两个数据集合分别进行左外连接和右外连接,然后再使用消去重复行的并操作将上述两个结果集合并为一个结果集。
在现实生活中,参照完整性约束可以减少对于全外连接的使用,一般情况下左外连接就足够了。在数据库中没有利用清晰、规范的约束来防范错误数据情况下,全外连接就变得非常有用了,你可以使用它来清理数据库中的数据。
select *
from  t_institution i
full outer join t_teller t
on i.inst_no = t.inst_no
2.3.4        外连接与条件配合使用
当在内连接查询中加入条件是,无论是将它加入到join子句,还是加入到where子句,其效果是完全一样的,但对于外连接情况就不同了。当把条件加入到join子句时,SQL Server、Informix会返回外连接表的全部行,然后使用指定的条件返回第二个表的行。如果将条件放到where子句中,SQL Server将会首先进行连接操作,然后使用where子句对连接后的行进行筛选。下面的两个查询展示了条件放置位子对执行结果的影响:
条件在join子句
select *
from  t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
and i.inst_no = “5801”
结果是:
inst_no    inst_name            inst_no    teller_no  teller_name
5801       天河区               5801       0001       tom
5801       天河区               5801       0002       david
5802       越秀区
5803       白云区
条件在where子句
select *
from  t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
where i.inst_no = “5801”
结果是:
inst_no    inst_name            inst_no    teller_no  teller_name
5801       天河区               5801       0001       tom
5801       天河区               5801       0002       david

2.4 自身连接
自身连接是指同一个表自己与自己进行连接。这种一元连接通常用于从自反关系(也称作递归关系)中抽取数据。例如人力资源数据库中雇员与老板的关系。
下面例子是在机构表中查找本机构和上级机构的信息。
select s.inst_no superior_inst, s.inst_name sup_inst_name, i.inst_no, i.inst_name
from t_institution i
join t_institution s
on i.superior_inst = s.inst_no

结果是:
superior_inst sup_inst_name        inst_no    inst_name
800           广州市               5801       天河区
800           广州市               5802       越秀区
800           广州市               5803       白云区

2.5 交叉(无限制) 连接
交叉连接用于对两个源表进行纯关系代数的乘运算。它不使用连接条件来限制结果集合,而是将分别来自两个数据源中的行以所有可能的方式进行组合。数据集合中一的每个行都要与数据集合二中的每一个行分别组成一个新的行。例如,如果第一个数据源中有5个行,而第二个数据源中有4个行,那么在它们之间进行交叉连接就会产生20个行。人们将这种类型的结果集称为笛卡尔乘积。
大多数交叉连接都是由于错误操作而造成的;但是它们却非常适合向数据库中填充例子数据,或者预先创建一些空行以便为程序执行期间所要填充的数据保留空间。
select *
from  t_institution i
cross join t_teller t
在交叉连接中没有on条件子句

原文地址:https://www.cnblogs.com/godwar/p/1583159.html