金典 SQL笔记(8)

------------------------文本方便拷贝------------------------

page269-301子查询

--子查询
--SQL允许将一个查询语句作为一个结果集供其他 SQL语句使用, 就像使用
--普通的表一样,被当做结果集的查询语句被称为子查询
--所有可以使用表的地方都可以使用子查询 ,比如select * from T
--上面的T 就可以用子查询来代替 select * from (select * from T2 where
--age >= 30) 这里(select * from T2 where age >= 30) 就是子查询
--可以将子查询看做为一张临时表 ,这张表在查询开始的时候被创建 ,在查询结束
--的时候被销毁子查询大大简化了复杂的 SQL 语句编程

--建表及测试数据
--T_Reader 读者信息FYearOfBirth 读者出身年份 FProvince读者省份
--FYearOfJoin 读者入会年份
CREATE TABLE T_Reader(Fid INT NOT NULL,FName VARCHAR(50 ),
FYearOfBirth INT, FCity VARCHAR( 50),FProvince VARCHAR(50 ),
FYearOfJoin INT)

--书籍信息FYearPublished 初版年份FCategoryId所属分类
CREATE TABLE T_Book(Fid INT NOT NULL,FName VARCHAR(50 ),
FYearPublished INT, FCategoryId INT)

--分类信息
CREATE TABLE T_Category(FId INT NOT NULL,FName VARCHAR(50 ))

--T_ReaderFavorite 读者和类别的对应关系 FReaderId读者主键
--FCategoryId分类主键
CREATE TABLE T_ReaderFavorite(FCategoryId INT,FReaderId INT)

--测试数据
INSERT INTO T_Category(FId ,FName) VALUES(1 ,'Story') --故事
INSERT INTO T_Category(FId ,FName) VALUES(2 ,'History') --历史
INSERT INTO T_Category(FId ,FName) VALUES(3 ,'Theory') --理论
INSERT INTO T_Category(FId ,FName) VALUES(4 ,'Technology') --技术
INSERT INTO T_Category(FId ,FName) VALUES(5 ,'Art') --艺术
INSERT INTO T_Category(FId ,FName) VALUES(6 ,'Philosophy') --哲学
                                                     --
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(1 ,'Tom', 1979,'TangShan' ,'Hebei', 2003)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(2 ,'Sam', 1981,'LangFang' ,'Hebei', 2001)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(3 ,'Jerry', 1966,'DongGuan' ,'DongGuan', 1995)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(4 ,'Lily', 1972,'JiaXing' ,'ZheJiang', 2005)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(5 ,'Marry', 1985,'BeiJing' ,'BeiJing', 1999)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(6 ,'Kelly', 1977,'ZhuZhou' ,'HuNan', 1995)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(7 ,'Tim', 1982,'YangZhou' ,'HuNan', 2001)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(8 ,'King', 1979,'JiNan' ,'ShanDong', 1997)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(9 ,'John', 1979,'QingDao' ,'ShanDong', 2003)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(10 ,'Lucy', 1978,'LuoYany' ,'HeNan', 1996)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(11 ,'July', 1983,'ZhuMaDian' ,'HeNan', 1999)
INSERT INTO T_Reader(Fid ,FName, FYearOfBirth,FCity ,FProvince, FYearOfJoin)
VALUES(12 ,'Fige', 1981,'JinCheng' ,'ShanXi', 2003)   

INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(1 ,'About J2EE', 2005,4 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(2 ,'Learning Hibernate', 2003,4 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(3 ,'Two Cites', 1999,1 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(4 ,'Jane Eyre', 2001,1 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(5 ,'Oliver Twist', 2002,1 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(6 ,'HisTory of china', 1982,2 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(7 ,'HisTory of England', 1860,2 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(8 ,'HisTory of America', 1700,2 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(9 ,'HisTory of the World', 2008,2 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(10 ,'Atom', 1930,3 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(11 ,'RELATIVITY', 1945,3 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(12 ,'Computer', 1970,3 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(13 ,'Astronomy', 1971,3 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(14 ,'How To Singing', 1771,5 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(15 ,'DaoDeJing', 2001,6 )
INSERT INTO T_Book(Fid , FName, FYearPublished, FCategoryId )
VALUES(16 ,'ObediencetoAuthority', 1995,6 )

INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(1 ,1)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(5 ,2)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(2 ,3)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(3 ,4)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(5 ,5)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(1 ,6)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(1 ,7)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(4 ,8)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(6 ,9)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(5 ,10)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(2 ,11)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(2 ,12)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(1 ,12)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(3 ,1)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(1 ,3)
INSERT INTO T_ReaderFavorite(FCategoryId , FReaderId)
VALUES(4 ,4)

--子查询有两种类型,一种是只返回一个单值的子查询 ,这时它可以
--用在单值可以使用的地方 ,可以把它看成一个拥有返回值的函数
--另外一种是返回一列值的子查询 ,这时的子查询可以看成在内存
--中的临时表

--单值子查询
--单值子查询的限制,返回值必须只有一行记录 ,而且只能有一个列,
--这样的子查询又被称为标量子查询标量子查询可以在 select语句
--表达式中, 以及where语句中等很多场合
--范例select 语句列表中使用 ,可以把它看成函数就易懂了
SELECT 1 AS f1,2 ,(SELECT MIN(FYearPublished ) FROM T_Book),
(SELECT MAX(FYearPublished ) FROM T_BOOK ) AS f4

--范例列值子查询
SELECT T_Reader. FName,t2 .FYearPublished, t2.FName
FROM T_Reader,( SELECT * FROM T_Book WHERE FYearPublished < 1800 ) t2

--单值子查询扩展进阶
--这个子查询,可以 SELECT MAX(FYearPublished) FROM T_BOOK 选中直接执行
select FId, FName,(SELECT MAX( FYearPublished) FROM T_BOOK )
FROM T_Category
--升级下
--这个子查询无法选中单独执行 ,上个子查询没有依赖外部查询字段 ,所以可以
--单独选中执行
--从而能查询到一类图书最新出版的年份
select FId, FName,
(SELECT MAX(FYearPublished ) FROM T_BOOK
 WHERE T_BOOK .FCategoryId = T_Category.FId )
FROM T_Category

--where 子句中的标量查询
--标量子查询不仅可以在select语句的列表中 ,还可以用在where子句中 ,而且
--实际应用的子查询很多时候都是用在 where子句中的
select FReaderId from dbo.T_ReaderFavorite
WHERE FCategoryId =
(SELECT FId from T_Category WHERE FName = 'Story')

--首先建立内连接
--可以查看俩表的交集
--然后根据年份条件筛选利用子查询查找最早的初版年份
select c. FId,b .FName, b.FYearPublished
FROM T_Book AS b INNER JOIN T_Category AS c
ON b. FCategoryId = c .FId
WHERE b. FYearPublished =
(SELECT MIN(FYearPublished ) FROM T_Book WHERE T_Book .FCategoryId = c.FId)

--集合运算符in,any,all,exists 与子查询的结合
--如果子查询是多行多列,这样的子查询可以作为临时表
--如果子查询是多行当列,这样的子查询其实是一个结果集
--SQL 对这样的结果集提供了in,any,all exeists 等操作符

--需求: 检索所有图书出版年份内入会的读者信息
SELECT * FROM T_Reader
WHERE FYearOfJoin IN
(select FYearPublished FROM T_BOOK)

--SQL 中any 和some使用和功能都是相同的和 in运算符不同
--any必须和其他比较运算符共同使用 ,而且比较将比较运算符放
--在any 关键字符前 ,所比较的值也需求匹配子查询中的任意值
SELECT * FROM T_Reader
WHERE FYearOfJoin =any
(select FYearPublished FROM T_BOOK)
--这个查询结果和上面in的查询结果一样的
--也就是说'=any' 等价于In 运算符
--而'<>any' 等价于not in 运算符
--但是像'<any' 就没法等价了还有其他更详细的需要看
--TSQL 技术解密可以更深入

--查找任何一个会员出生前初版的图书
SELECT * FROM T_Reader
WHERE FYearOfJoin <any
(select FYearPublished FROM T_BOOK)

--ALL运算符
--ALL 运算符要求比较的值需要匹配子查询中的所有值
--ALL 运算符同样不能单独使用 ,必须和比较运算符共同使用
--下面的SQL 语句用来检索在所有会员入会之前出版的图书 :
SELECT * FROM T_Book
WHERE FYearPublished <ALL
(SELECT FYearOfJoin FROM T_Reader)

--上面那个不是等同于可以用 min函数取最小值
SELECT * FROM T_Book
WHERE FYearPublished <( SELECT min (FYearOfJoin) FROM T_Reader )
--ALL运算符同样不能与固定的集合匹配 ,比如下面的SQL是错误的
SELECT * FROM T_Book WHERE FYearPublished <ALL( 2001,2002 ,2003)
--不过这个限制并不会妨碍功能的实现 ,因为没有必要对固定的集合进行
--ALL匹配由于带匹配的集合固定完全可以由其他方式实现诸如
SELECT * FROM T_Book WHERE FYearPublished < 2001

--当使用ALL 运算符的时候 ,如果待匹配的集合为空,也就是子查询没有
--返回任何数据的时候,不论与什么比较符搭配使用 ALL返回的值永远是
--true. 如下这个查询语句FProvince='没有省份 ' 查询出来是没有匹配
--数据的, 但是结果上面的思维 ,会把T_Book 所有数据查询出来 ;
--按照正常的思维返回的结果应该是空才对 ALL运算符的语义就是这样
--使用的时候格外注意
SELECT * FROM T_Book
WHERE FYearPublished <ALL
(SELECT FYearOfJoin FROM T_Reader
 WHERE FProvince ='没有省份 ')

 --exists 运算符
 --和 in ,any,all 运算符不同exists运算符是单目运算符 ,它不与列匹配
 --因此它也不要求待匹配的集合是单列的 exists运算符用来检查每一行
 --是否匹配子查询 ,可以认为exists 就是用来测试子查询的结果是否为空的
 --,如果结果集为空则匹配结果为 false,否则匹配结果为true
 --EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不
 --返回任何数据,而是返回值 True或False
 --EXISTS 指定一个子查询,检测行的存在。

 --下面三个结果都相同
 SELECT * FROM T_BOOK
WHERE EXISTS
(SELECT FName FROM T_Reader
 WHERE FProvince = 'ShanXi' )

SELECT * FROM T_BOOK
WHERE EXISTS
(SELECT Null)

 SELECT * FROM  T_BOOK

--从前面几个例子来看,使用 exists运算符要么是匹配返回表中的所有
--数据, 要么就是不匹配不返回任何数据 ,好像exists 运算符并没有太
--大意义其实上面的例子在实际中并不实用 ,exists要和相关子查询
--一起使用才有意义在相关子查询中引用外部查询中的这个字段 ,这样
--匹配外部子查询中的每行数据的时候 ,相关子查询就会根据当前行的
--信息来进行匹配判断,这样就可以实现非常丰富的功能呢

--测试下和in 的区别
SELECT * FROM T_BOOK
WHERE FCategoryId IN
(SELECT Fid from T_Category WHERE FName = 'History')

SELECT * FROM T_BOOK
WHERE EXISTS
(SELECT Fid from T_Category WHERE FName = 'History'
AND Fid = T_BOOK.FCategoryId )

--其他类型SQL 语句中的子查询
--子查询在insert 中的应用
--将查询出来的结果批量插入
--语法字段需要一一对应
--insert into T_ReaderFavorite2(FCategoryId,FReaderId)
--SELECT FCategoryId,FReaderId FROM T_ReaderFavorite2
--还有其它附加条件where 计算等都可以只需要对应字段类型

--子查询在update 语句中的应用
--范例
UPDATE T_Book
SET FYearPublished =
(SELECT MAX(FYearPublished ) FROM T_Book)

--范例
--所有同类书超过本的图书初版日期改为
--UPDATE T_Book b1
--SET FYearPublished = 2005
--WHERE (SELECT COUNT(*) FROM T_Book2 b2
--       WHERE b1.FCategoryId=b2.FCategoryId)>3

--子查询在delete 语句中的应用
--删除同类书超过本
delete T_Book b1
WHERE ( SELECT COUNT (*) FROM T_Book2 b2
       WHERE b1. FCategoryId=b2 .FCategoryId)> 3

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-03 00:58:04

金典 SQL笔记(8)的相关文章

金典 SQL笔记(6)

page223-索引 --利用SQL 语句创建索引 --CREATE INDEX 索引名称on 表名(字段 ,字段, 字段字段n) --索引名称必须为唯一的,字段 ,字段, 同意一个到多个 --范例为T_person 表中给FName创建索引索引名为 idx_person_name CREATE INDEX idx_person_name ON T_Person (FName) --删除索引 --drop index 表名索引名 DROP INDEX T_person.idx_person_na

金典 SQL笔记(3)

由于在本地笔记上写的.CSDN markdown编辑器仅仅支持.md格式导入, 图片没办法直接导进去.写的多了懒的一张一张图片切图上传; 直接整个文章切成图片上传上去了.

金典 SQL笔记(1)

page(1-75) 主键最好是无意义的字段便于以后扩展. PS:假设以标书编码为主键,以后标书编码填错需要改的时候,关联表都需要跟着改.如果是一个无意义的自增字段是主键就无此原因. 主键最好不要设置为联合主键,否则降低效率,不利于扩展 PS:原文[联合主键可以解决表中没有唯一主键的问题,不过联合主键有如下缺点:] 1.效率低.在进行数据的添加.删除.查找及更新的时候,数据库系统必须处理俩个字段,这样大大降低了数据的处理速度. 2.使数据库的结构设计变得槽糕.组成联合主键的字段通常都是有业务含义

金典 SQL笔记(9)

page301-354其它解决方式 ---开窗函数 --測试数据及表 USE [NB] GO /****** 对象: Table [dbo].[T_Person2] 脚本日期: 08/14/2015 11:24:46 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[T_Person3] ( [FName] [varchar] (20) NULL,

金典 SQL笔记 SQL语句汇总

SELECT * FROM (SELECT ROW_NUMBER() OVER ( ORDER BY id) AS rowN,FNumber, FName,FSalary ,Fage FROM dbo. T_Employee) AS a WHERE a. rowN >=3 AND a. rowN <=5 SELECT distinct CREATEDate,state FROM dbo .TwodimensionalcodeHistory SELECT * FROM Twodimensiona

金典 SQL笔记(2)

因为在本地笔记上写的.CSDN markdown编辑器只支持.md格式导入, 图片没办法直接导进去.写的多了懒的一张一张图片切图上传; 直接整个文章切成图片上传上去了. 版权声明:本文为博主原创文章,未经博主允许不得转载.

金典 SQL笔记(4)

因为在本地笔记上写的.CSDN markdown编辑器只支持.md格式导入, 图片没办法直接导进去.写的多了懒的一张一张图片切图上传; 直接整个文章切成图片上传上去了. 版权声明:本文为博主原创文章,未经博主允许不得转载.

金典 SQL笔记(7)

附上文本方便拷贝 page247-表连接269 --表连接 --建表及测试数据 --T_Customer 客户信息表 --T_OrderType 订单类型 --T_Order 订单信息 CREATE TABLE T_Customer(Fid INT NOT NULL,FName VARCHAR(20 ) NOT NULL, Fage INT, PRIMARY KEY (Fid)) CREATE TABLE T_Order(Fid INT NOT NULL,FNumber VARCHAR(20 )

金典 SQL笔记(5)

版权声明:本文为博主原创文章,未经博主允许不得转载.