五、表连接

当数据表中存在许多重复的冗余信息时,就要考虑将这些信息建在另一张新表中,在新表中为原表设置好外键,在进行数据查询的时候,就要使用到连接了,表连接就好像两根线,线的两端分别连接两张表的不同字段上,将两个字段进行关联。表连接分为内连接(inner join)、交叉连接、自连接和外连接等。

1、内连接,语法  inner join table_name on condition ,table_name被关联的表名,condition关联条件。

例如:有两张表,T_Customer保存着客户的Id,姓名,年龄等信息,T_Order表保存着订单号及订单价格等信息,T_Order中FCustomerId是T_Customer中的FId的外键,下面查询客户姓名为Mike的客户的订单号及订单价格。

select c.FName,o.FNumber,o.FPrice
from T_Order  o
inner join T_Customer c on o.FCustomerId=c.FId 
where c.FName='Mike'

2、交叉连接,与内连接相比,交叉连接非常简单,不需要on子句,交叉连接将表中的所有记录都包含到结果集中,交叉连接分为隐式的连接和显示的cross join 连接,其中隐式的交叉连接,所有数据库都支持,cross join显示的交叉连接DB2数据库不支持。例如:查询上两张表中客户的Id,姓名,年龄以及订单信息。

--  隐式的交叉连接
select  T_Customer.Id,T_Customer.FName,T_Customer.FAge,TOrder.FName,TOrder.FNumber
from T_Customer ,TOrder
--  显示的交叉连接
select  T_Customer.Id,T_Customer.FName,T_Customer.FAge,TOrder.FName,TOrder.FNumber
from T_Customer  across join TOrder

3、自连接,其主要用途就是检索一张表中的内部情况,例如检索表T_Order中订单类型相同的订单的列表。

select o1.FNumber ,o1.FName,o1.FType, o2.FNumber ,o2.FName,o2.FType
from T_Order o1 
inner join T_Order o2 on o1.FType=o2.FType and o1.FId <o2.FId 

(至于为什么要加上and后面的约束及为什么不是 o1.FId <>o2.FId ,感兴趣的朋友我们可以自己试一试,因为存在着信息重复的问题,我们也可以继续交流)

4、外连接,内连接要求连接的两张表必须有匹配的记录,但是如果说T_Order表中的FCustomerId一列有null值,那么内连接是无法将这条信息查询出来的,但是我们是需要这条数据的,这样就需要外部连接了,外连接包括左外连接,右外连接和全外连接,全外连接在数据库MySql中是不支持的,所以,可以使用union all 联合两个查询语句,即左外连接查询和右外连接查询。

左外连接就是将左表中的所有数据,无论是否满足on后面的条件语句,都匹配出来。右外连接就是将右表中的所有数据,无论是否满足on后面的条件语句,都匹配出来。而全外连接,就是将两张表中的所有数据,无论是否满足on后面的条件语句,都匹配出来。

-- 左外连接,取出左表T_Customer中的所有数据,无论是否匹配 T_Customer.FId =T_Order.FCustomerId
select  c.FNumber ,C.FName,o.FNumber ,o.FPrice
from T_Customer c 
left outer join T_Order o on T_Customer.FId =T_Order.FCustomerId
-- 右外连接,取出右表T_Order中的所有数据,无论是否匹配 T_Customer.FId =T_Order.FCustomerId
select  c.FNumber ,C.FName,o.FNumber ,o.FPrice
from T_Customer c 
right  outer join T_Order o on T_Customer.FId =T_Order.FCustomerId
-- 全外连接,取出两张表中的所有数据,无论是否匹配 T_Customer.FId =T_Order.FCustomerId
select  c.FNumber ,C.FName,o.FNumber ,o.FPrice
from T_Customer c 
full outer join T_Order o on T_Customer.FId =T_Order.FCustomerId

六、子查询

sql允许将一个查询语句作为结果集提供给其它sql语句使用,被当做结果集的查询语句就是子查询,可以将子查询看做是一张临时生成的数据表(此时的搜索结果必须是多行多列),这张数据表在开始时被创建,在查询结束时被删除。子查询可以用在select语句,insert语句以及update语句。子查询大大简化了sql语句的编写,提高了效率,但是如果使用不当,容易造成性能问题。

1、单值子查询

单值子查询和普通的sql语句没什么区别,唯一的限制就是子查询的返回值必须只有一行记录,而且只能有一个列,这样的子查询也称作标量子查询。

select 1 as f1 ,2 ,(select MIN (FYearOfPublish)from T_Book ) as N'最早出版年份',
(select MAX (FYearOfPublish) from T_Book )as N'最晚出版年份'

2、列值子查询

与标量子查询不同,列值子查询可以返回一个多行多列的结果集,又称为表子查询,可以看做一个临时的表。

--查询出版日期在1800年以前的书的名字及作者的名字,当然这个地方用到了交叉连接的隐式实现
select r.FName ,b.FName ,b.FYearOfPublish
from T_Reader r,(select FName ,FYearOfPublish from T_Book where FYearOfPublish <1800) b

3、select语句中的标量子查询

标量子查询唯一的限制就是子查询的返回值必须只有一行记录,而且只能有一个列,其实标量子查询完全可以返回随当前记录变化而变化的值。比如:

--返回每一类图书的最新出版年份,图书类别
select FId ,FName,
(
select MAX (FYearOfPublish)from T_Book b
where b.FCategoryId =c.FId )as N'最新出版年份'
from T_Categroy c

4、where语句中的标量子查询

标量子查询不仅可以用在select语句中,而且可以用在where语句中,比如:

--返回最喜欢读的书籍类别为Story的读者的ID信息
select FReaderId from T_ReaderFavorite
where FCategoryId =
(
select FId from T_Categroy
where FName ='Story'
)

再看一个综合点的例子:假设需要检索每一种书籍类别中出版年份最早的书籍的名称,如果有两本或两本以上的,则都显示他们的名字。要求检索结果中显示类型的名字、书的名字和它的出版年份。

select T_Categroy .FName ,T_Book .FName ,T_Book .FYearOfPublish  
from T_Book inner join T_Categroy on T_Book .FCategoryId =T_Categroy .FId 
where T_Book .FYearOfPublish =
(
    select MIN (T_Book .FYearOfPublish) from T_Book
    where T_Book .FCategoryId =T_Categroy .FId  
)

当然上面的语句中也可以使用别名代换,这样会更简明些。

5、集合运算符与子查询,如果子查询的结果集是多行多列的,那么可以将该子查询看做是一个临时的数据表,但是当结果集是一个多行单列的集合时,就需要使用in,any,all及exists等来查询。

in操作符,是用来匹配多行单列的,可以简单的匹配一个集合中的某一项,比如检索在2001,2003,2005年出版的所有图书

select * from T_Book where FYearofPublish in (2001,2003,2005)
select * from T_Reader where FYearofJoin in (select FYearofPublis from T_Book)


any必须和其他的比较运算符(=,<,>,!=)共同使用,不严谨的说你可以这样认为,any就是任何一个,匹配任何一个的意思,比如

select * from T_Reader where FYearOfJoin =any (  select FYearOfPublish  from T_Book )
select * from T_Reader where FYearOfJoin <>any (  select FYearOfPublish  from T_Book )



这两条语句前一条=any其效果适合in一样的,<>any 效果适合not in 一样的,除了=运算符,any还可以和大于小于大于等于等运算符共同使用,例如:

-- 查询在所有会员出生之前出版的书
select * from T_Book where FYearOfPublish <any( select FYearOfBith from T_Reader)

exists,是否存在比较运算符,其后面的语句如果为真则返回true,否则返回false。先看一个例子:

在这个事例中,如果T_Reader表中存在姓名为Tom的读者信息,那么将返回T_Book表中的信息,反之,不会检索出任何信息。也就是,如果存在,则返回,不存在,则查不到任何信息,看似好像exists的作用并不是很大,但是它往往用在子查询中引用外部字段的检索中,看实例:

-- 检索1950年以前出版的图书的图书类别
select * from T_Category where exists (select * from T_Book where T_Book.FCategoryId =T_Category.Id and T_Book .FYearofPublis <1950 )

这样就会检索出在1950年以前出版的图书的信息了。

七、子查询在insert语句update语句中的应用

insert语句:一般的,向一个数据表中添加一条数据就是应用insert into 表名(字段1,字段2……)values (值1,值2,……) 比如

insert into T_Person(FId ,FName,FAge) values (1,'Tom',20)

但其实insert还有另外一种用法,就是insert ……select……语句,具体语法为insert into 表名(字段1,字段2……)select (值1,值2,……) from 表

insert into T_Reader2(FId,FName,FAge) select (FId,FName,FAge) from T_Reader

这条语句其实就相当于复制了一个T_Reader表,将其信息插入到了T_Reader2 中。当然,insert……select 还有更复杂的用法,可以向不同结构的表中插入数据,例如:为每个读者的爱好增加“小说”,也就是为每一个读者在其T_ReaderFavorite中添加一条FCategory=1的记录(如果原先读者已经有了此爱好,就不用添加,如果没有此爱好,就添加)。

insert into T_ReaderFavorite(FCategoryId ,FReaderId ) select 1,FId from T_Reader 
where not exists
(
  select * from T_ReaderFavorite  where T_ReaderFavorite .FCategoryId =1 and  T_ReaderFavorite .FReaderId =T_Reader .FId 
)

update语句:在update语句中子查询也可以有比较复杂的检索,例如:将所有同类图书的本数超过3本的图书的出版日期更新为2008(自连接)

update T_Book set FYearOfPublish =2008 where (select COUNT (*) from T_Book bk2 where bk2 .FCategoryId =T_Book .FCategoryId )>3

delete语句:例如:将所有同类图书的本数超过3本的图书删除

delete from T_Book where (select count(*) from T_Book bk where bk.FCategoryId=T_Book.FCategoryId)>3

MS sql server 基础知识回顾(二)-表连接和子查询的更多相关文章

  1. SQL server基础知识(表操作、数据约束、多表链接查询)

    SQL server基础知识 一.基础知识 (1).存储结构:数据库->表->数据 (2).管理数据库 增加:create database 数据库名称 删除:drop database ...

  2. Sql Server 基础知识

    Sql Server 基础知识: http://blog.csdn.net/t6786780/article/details/4525652 Sql Server 语句大全: http://www.c ...

  3. ylb:SQL 表的高级查询-多表连接和子查询

    ylbtech-SQL Server: SQL Server-表的高级查询-多表连接和子查询 SQL Server 表的高级查询-多表连接和子查询. 1,ylb:表的高级查询-多表连接和子查询 返回顶 ...

  4. MySQL多表查询之外键、表连接、子查询、索引

    MySQL多表查询之外键.表连接.子查询.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为 ...

  5. MySQL开发——【联合查询、多表连接、子查询】

    联合查询 所谓的联合查询就是将满足条件的结果进行拼接在同一张表中. 基本语法: select */字段 from 数据表1 union [all | distinct] select */字段 fro ...

  6. SQL Server 基础知识/数据类型/数值类型

    数据库设计简单地来讲,也就是设计表格的过程. 表格存储的数据是可以理解为一个二维表,由行和列组成. 原则上来讲,一个数据库只需要一个字段,一个数据类型就可以解决所有的问题,但是这样做并不明智,所以一般 ...

  7. SQL Server基础知识

    1.SQL Server表名为什么要加方括号? 这个不是必须要加,但表名或字段名如果引用了sqlserver中的关键字,数据库会不识别这到底是关键字还是表名(或字段名)时就必须要加. 比如,一个表名叫 ...

  8. SQL Server 基础之《学生表-教师表-课程表-选课表》

    一.数据库表结构及数据 建表 CREATE TABLE Student ( S# INT, Sname ), Sage INT, Ssex ) ) CREATE TABLE Course ( C# I ...

  9. SQL Server 基础 01 数据库、表操作

    对着书慢慢学习,一天一点点! 数据库操作 (create.alter.drop)  --3-3-1 /create database 语句创建数据库 create database testSQL - ...

随机推荐

  1. 腾讯优测-优社区干货精选 |  那些年,我们在Android机型适配上遇到的坑之Camera拍照时快门咔嚓声

    文/腾讯优测研发工程师 吴宇焕 优测小优有话说: android机型适配的坑自然是不少,不想掉坑快来优测优社区~ 现在Android手机一般都会带有照相功能,有很多朋友就发现手机照相时快门声音很响,想 ...

  2. c语言二叉树基本操作

    编译器为vs2013 #include "stdafx.h" #include<malloc.h> #include<stdlib.h> #define O ...

  3. C++ Primer : 第十三章 : 拷贝控制之对象移动

    右值引用 所谓的右值引用就是必须将引用绑定到右值的引用,我们通过&&来绑定到右值而不是&, 右值引用只能绑定到即将销毁的对象.右值引用也是引用,因此右值引用也只不过是对象的别名 ...

  4. SQL Server使用convert对datetime日期数据进行获取

    来源:http://database.51cto.com/art/201007/211883.htm 备注:本文的语法讲解确实是比较乱,似乎格式不太严谨.参考时还是以实例验证为准比较好 以下的文章主要 ...

  5. Squid代理服务器的安装与配置

    一.简介 代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息. Squid是一个缓存Internet 数据的软件,其接收用户的下载申请,并自动处理所下载的数据.当一个用 ...

  6. MySql取得日期(前一天、某一天)

    在测试一个统计表格,发现每次手写一个地址实在很烦,干脆就搞个自动计算好时间区间的东西.以下内容作为收获吧! 取得当天: SELECT curdate(); mysql> SELECT curda ...

  7. Vue知识点

    1. Vue生命周期图示: 2.插值: 文本:{{ message }}: 纯html:v-html="xxx"; 属性:v-bind:id="xxx"; 使用 ...

  8. Symfony2创建基于域名的路由(原创翻译)

    你可以匹配将要来到的请求以HTTP域名的方式 YAML方式 mobile_homepage: path: / host: m.example.com defaults: { _controller: ...

  9. Win7 远程桌面 错误代码:5 异常处理(您的远程桌面会话即将结束 此计算机的虚拟内存可能不足。请关闭其他程序,然后重试连接远程计算机。如果问题仍然存在,请联系网络管理员或技术支持。)

    问题表现: 在用windows7 远程桌面连接其他电脑时,出现错误提示对话框—-标题为“严重错误(错误代码:5)”,内容为“您的远程桌面会话即将结束 此计算机的虚拟内存可能不足.请关闭其他程序,然后重 ...

  10. Visual.Studio.2013.IDE+visual.studio.15.preview5 编译器

    硬盘版Visual.Studio.2013.IDE + visual.studio.15.preview5 编译器 使用前注意以下事项: 1.右键-管理员权限安装,VS15补丁.exe,补丁是VS15 ...