MS sql server 基础知识回顾(二)-表连接和子查询
五、表连接
当数据表中存在许多重复的冗余信息时,就要考虑将这些信息建在另一张新表中,在新表中为原表设置好外键,在进行数据查询的时候,就要使用到连接了,表连接就好像两根线,线的两端分别连接两张表的不同字段上,将两个字段进行关联。表连接分为内连接(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 基础知识回顾(二)-表连接和子查询的更多相关文章
- SQL server基础知识(表操作、数据约束、多表链接查询)
SQL server基础知识 一.基础知识 (1).存储结构:数据库->表->数据 (2).管理数据库 增加:create database 数据库名称 删除:drop database ...
- Sql Server 基础知识
Sql Server 基础知识: http://blog.csdn.net/t6786780/article/details/4525652 Sql Server 语句大全: http://www.c ...
- ylb:SQL 表的高级查询-多表连接和子查询
ylbtech-SQL Server: SQL Server-表的高级查询-多表连接和子查询 SQL Server 表的高级查询-多表连接和子查询. 1,ylb:表的高级查询-多表连接和子查询 返回顶 ...
- MySQL多表查询之外键、表连接、子查询、索引
MySQL多表查询之外键.表连接.子查询.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为 ...
- MySQL开发——【联合查询、多表连接、子查询】
联合查询 所谓的联合查询就是将满足条件的结果进行拼接在同一张表中. 基本语法: select */字段 from 数据表1 union [all | distinct] select */字段 fro ...
- SQL Server 基础知识/数据类型/数值类型
数据库设计简单地来讲,也就是设计表格的过程. 表格存储的数据是可以理解为一个二维表,由行和列组成. 原则上来讲,一个数据库只需要一个字段,一个数据类型就可以解决所有的问题,但是这样做并不明智,所以一般 ...
- SQL Server基础知识
1.SQL Server表名为什么要加方括号? 这个不是必须要加,但表名或字段名如果引用了sqlserver中的关键字,数据库会不识别这到底是关键字还是表名(或字段名)时就必须要加. 比如,一个表名叫 ...
- SQL Server 基础之《学生表-教师表-课程表-选课表》
一.数据库表结构及数据 建表 CREATE TABLE Student ( S# INT, Sname ), Sage INT, Ssex ) ) CREATE TABLE Course ( C# I ...
- SQL Server 基础 01 数据库、表操作
对着书慢慢学习,一天一点点! 数据库操作 (create.alter.drop) --3-3-1 /create database 语句创建数据库 create database testSQL - ...
随机推荐
- python数据结构与算法——字典树
class TrieTree(): def __init__(self): self.root = {} def addNode(self,str): # 树中每个结点(除根节点),包含到该结点的单词 ...
- python import eventlet包时提示ImportError: cannot import name eventlet
root@zte-desktop:/home/ubuntu/python-threads# cat eventlet.py #!/usr/bin python import eventlet from ...
- ubuntu下mysql的常用命令,MySQL数据库的基本操作命令
一.mysql服务操作 0.查看数据库版本 sql-> status; 1.net start mysql //启动mysql服务 2.net stop mysql //停止mysql服务 3 ...
- mysql添加外键
语法:alter table 表名 add constraint FK_ID foreign key(你的外键字段名) REFERENCES 外表表名(对应的表的主键字段名); 例: alter ta ...
- Bean的定义及作用域的注解实现
1. Classpath扫描与组件管理 从Spring3.0开始,Spring JavaConfig项目提供了很多特性,包括使用java而不是XML定义bean. 比如@configuration, ...
- 不同操作系统上屏蔽oracle的操作系统认证方式
windows系统上>如果不想用户通过操作系统验证方式登录,可以修改 sqlnet.ora文件,把 SQLNET.AUTHENTICATION_SERVICES=NTS 前面加#注释掉就可以了. ...
- HTML5外包团队-技术分享【使用HTML5的VIDEO标记播放RTSP视频流】
使用HTML5的VIDEO播放RTSP实时视频流源代码: <!DOCTYPE html> <html><head> <meta http-equiv=&quo ...
- HBase使用场景和成功案例 (转)
HBase 使用场景和成功案例 有时候了解软件产品的最好方法是看看它是怎么用的.它可以解决什么问题和这些解决方案如何适用于大型应用架构,能够告诉你很多.因为HBase有许多公开的产品部署,我们正好可以 ...
- PHPMyAdmin 显示缺mysqli 扩展的解决方法
今天在学PHP100视频教程时,装了phpMyAdmin.一开始下载的是最新版本phpMyAdmin-4.1.4-all-languages, 直接500错误,页面怎么也打不开.我用的PHP版本是老版 ...
- POJ解题经验交流
感谢范意凯.陈申奥.庞可.杭业晟.王飞飏.周俊豪.沈逸轩等同学的收集整理. 题号:1003 Hangover求1/2+1/3+...1/n的和,问需多少项的和能超过给定的值 类似于Zerojudg ...