打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SQL-- JOIN之完全用法(版本2)【转】

在我叙述 JOIN 的用法前,我先引用数据库设计中最常见的范式资料。

第三范式( 3NF ):如果关系模式 R U F )中的所有非主属性对任何候选关键字都不存在传递信赖,则称关系 R 是属于第三范式的。

例:如 S1 SNO SNAME DNO DNAME LOCATION 各属性分别代表学号,姓名,所在系,系名称,系地址。

关键字 SNO 决定各个属性。由于是单个关键字,没有部分依赖的问题,肯定是 2NF 。但这关系肯定有大量的冗余,有关学生所在的几个属性 DNO DNAME LOCATION 将重复存储,插入,删除和修改时也将产生类似以上例的情况。

原因:关系中存在传递依赖造成的。由于 SNAME DNO 是依赖 SNO ,而 DNAME LOCATION 是依赖 DNO 的,即通过一个学号可以知道该学生的姓名以及他所在系代码,但无法由学号知道系地址,学号和系地址间是通过学号所对应的学生的所在系关联的,因此关键字SNO LOCATION 函数决定是通过传递依赖 DNO -> LOCATION 实现的。也就是说, SNO 不直接决定非主属性 LOCATION

解决目地:每个关系模式中不能留有传递依赖。

解决方法:分为两个关系 S SNO SNAME DNO ), D DNO DNAME LOCATION

注意:关系 S 中不能没有外关键字 DNO 。否则两个关系之间失去联系。

在数据库的设计过程中常常按照第三范式来设计数据库,当然在有些场合为优化数据库的性能而增加了相关冗余字段以使表的结构不符合 3NF ,在多数场合中,没有一张表能完整的发挥客户所需要的结果集。这样就需要通过联接多张在逻辑上存在依赖关系的表,选择你所需要的数据。   

在使用 JOIN 前,必须明白是通过联接,根据各个表之间的逻辑关系从相关表中检索数据。通过 SQL Server 自带帮助文件,可以清楚的知道:可在 FROM WHERE 子句中指定联接。

1.1.        WHERE 子句中指定联接

下例使用 WHERE子句进行表之间的

SELECTA.SYMBOL,A.SNAME,B.TDATE,B.CLOSE

FROM SECURITYCODE A,DAYQUOTE B

WHERE A.SYMBOL =B.SYMBOL

    AND B.TDATE >= A.LISTDATE

    ANDA.SYMBOL LIKE  '600%'

在上例中联接的表 A 与表 B 通过 A.SYMBOL =B.SYMBOL 这个条件联接,筛选条件为 B.TDATE 不小于 A. LISTDATE

WHERE 子句中指定联接,对于较简单的联接,使用这种方式可能较方便,但综合来说,不推荐使用该语法联接表。

1.2.        FROM 子句中指定联接

拿上面的例子来详细说,表 SECURITYCODE 中主要存放证券代码的基本信息,表中的 SYMBOL 代表股票代码, SNAME 代表股票名称, LISTDATE 代表上市日期;表 DAYQUOTE 中主要存放股票的每日行情。 SYMBOL 代表股票代码, TDATE 代表交易日期, CLOSE 代表收盘价。

我现在的取值逻辑是:取出股票代码以 600 打头的股票自上市日期以来的所有交易日的收盘价。将 SECURITYCODE DAYQUOTE 通过 SYMBOL 联接。

SELECTA.SYMBOL,A.SNAME,B.TDATE,B. CLOSE

FROM SECURITYCODE A

JOIN DAYQUOTE B

    ON A.SYMBOL =B.SYMBOL

WHERE  B.TDATE >=A.LISTDATE

    ANDA.SYMBOL LIKE '600%'

ORDER BY A.SYMBOL,B.TDATE

对于使用 FROM 子句方式联接表,可以很清楚的看出表之间的联接条件。就可读性以及后续的可修改性与 WHERE 子句相比有较大的优势。

下面就联接的方式引用帮助文件中的具体介绍,联接可以分为以下几种:

1.3.        内联接

内联接(典型的联接运算,使用像 = <> 之类的比较运算符)。包括相等联接和自然联接。

内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。

SQL-92 标准中,内联接可在 FROM WHERE 子句中指定。这是 WHERE 子句中唯一一种 SQL-92 支持的联接类型。 WHERE 子句中指定的内联接称为旧式内联接。

内联接一般常见写法:

SELECTA.COLUMN1,[A.COLUMN2],B.COLUMN1,[B.COLUMN2]

FROM  TABLE1 A

[INNER] JOIN TABLE2 B

    ONA.COLUMN0 = B.COLUMN0

在查询分析器中使用 INNER JOIN 时常常省略 INNER

1.4.        外联接

外联接可以是左向外联接、右向外联接或完整外部联接。

FROM 子句中指定外联接时,可以由下列几组关键字中的一组指定:

LEFT JOIN LEFTOUTER JOIN

左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。

RIGHT JOIN RIGHTOUTER JOIN

右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。

FULL JOIN FULLOUTER JOIN

完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。

仅当至少有一个同属于两表的行符合联接条件时,内联接才返回行。内联接消除与另一个表中的任何行不匹配的行。而外联接会返回 FROM 子句中提到的至少一个表或视图的所有行,只要这些行符合任何 WHERE HAVING 搜索条件。将检索通过左向外联接引用的左表的所有行,以及通过右向外联接引用的右表的所有行。完整外部联接中两个表的所有行都将返回。

外联接的中常见的是 LEFT JOIN ,将 LEFT JOIN 用熟已经可以解决大半问题了。

外联接的一般写法:

SELECTA.COLUMN1,[A.COLUMN2],B.COLUMN1,[B.COLUMN2]

FROM  TABLE1 A

LEFT|RIGHT|FULL [OUTER] JOINTABLE2 B

    ONA.COLUMN0 = B.COLUMN0

在查询分析器中使用 OUTERJOIN 时常常省略OUTER LEFT RIGHT 只是方向问题,在特定场合下, FULL OUTER JOIN 相当于 LEFT OUTER JOIN RIGHT OUTER JOIN 的消除重复行的合集。

1.5.        交叉联接

交叉联接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉联接也称作笛卡尔积。

没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。也就是说在没有WHERE 子句的情况下,若表 A 3 行记录,表 B 6 行记录 :

SELECT  A.*,B.* FROM A  CROSS  JOIN B

那以上语句会返回18 行记录。

 

假设有AB两个表。 

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并不以谁为基础,它只显示符合条件的记录
-------------------------------------------- 
PS:  
LEFT JOIN操作用于在任何的 FROM 子句中,组合来源表的记录。使用 LEFT JOIN 运算来创建一个左边外部联接。左边外部联 接将包含了从第一个(左边)开始的两个表中的全部记录,即使在第二个(右边)表中并没有相符值的记录。  

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

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

注:leftright是外连接,Inner是内连接。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
数据库基础笔记-SQL
经典SQL查询语句大全
SQL基础
SQL优化技巧 改善数据库性能
在VB6中用Select语句检索记录
python面试----连接、表操作
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服