金典 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 TwodimensionalcodeHistory

SELECT FName, Fage,FSubCompany FROM T_Employee
SELECT 'XXX 子公司' as CompanyName, '30000000' as RegAmount,FName, Fage,FSubCompany FROM T_Employee

--计算某几列的算数和
--FAge * FSalary 并非一个实际存在的列 ,可是他们在查询出来的数据中看起来是一个实际存在的字段 ,他们
--全然能够看成一个普通字段
SELECT FNumber, FName,FAge * FSalary AS FSalarIndex FROM T_Employee

--计算字符长度函数len(字段 )
SELECT FName, LEN(FName ) FROM T_Employee where FName IS NOT NULL

--截取字符串函数subString(字段 ,截取起始位置,截取长度 )  起始位置从開始
--我们截取从第二个字符開始開始截取 ,长度为位
SELECT FName, SUBSTRING(FName ,2, 3) FROM T_Employee WHERE FName IS NOT NULL


--多个函数嵌套计算正弦函数 ,和绝对值函数
SELECT FName, Fage,SIN (Fage), ABS(SIN (Fage)) FROM T_Employee

--java c# 中通过+ 来连接字符串 ,MS SQL中也能够这样
--假设第一个数字类型,sql会默认转换 +后面的格式为数字类型;假设转换失败则报错
SELECT 12+ '33','12' +'33', Fage+'1' ,FAge FROM T_Employee

CONCAT

--字符串拼接中MySQL最灵活能够使用 '+' 和Concat() 函数拼接;MS SQL中使用 '+'拼接
--Oracle 中使用'||' 双竖杆进行拼接等同于 '+' 也能够使用Concat()函数可是与 My Sql中的函数有所不同,仅仅支持俩个參数
--不支持俩个以上字符串的拼接须要达到 My Sql中的效果, 能够使用多个 Concat()函数嵌套使用;DB2 中也使用 '||'进行拼接
--DB2 中的Concat() 函数不会进行智能转换 ,假设带入数字不会直接转换为字符串 ,直接报错DB2 Concat() 函数也仅仅支持个參数
--不支持俩个以上字符串拼接
--语句拼接
SELECT ' 工号为'+ Fnumber+' 的员工姓名为 :'+Fname from T_Employee

--计算处于合理工资范围内的员工 (我们规定上限为年龄的+5000 和下限年龄的倍 +2000 为合理范围)
SELECT * FROM T_Employee WHERE FSalary BETWEEN Fage*1.5 +2000 AND Fage*1.8+ 5000

--不从实体表中取的数据
--MySql 和MSSql 同意使用不带 From子句的Select 语句来查询这些不属于不论什么实体表的数据
--在oracle 中不同意使用这种不带 From子句的select. 只是我们能够变通实现 from oracle中的系统表
--select 1,Length('abc') from DUAL
SELECT 1
SELECT LEN ('abc')
SELECT 1, 2,3 ,'a', 'b','c'

--联合结果集
--有时候我们须要组合俩个全然不同的查询结果集 ,而这俩个查询结果之间没有必的联系 ,仅仅是我们须要将他们显示在
--一个结果集中而已在SQL中能够使用 union 运算符来将俩个或者多个查询结果集联合为一个结果集中
--须要列数相同和相同位置的列字段类型相容 (技巧能够通过常量字段补足就好了 select '1',xxx from 表)
SELECT fnumber, fname,Fage FROM dbo. T_Employee
union
SELECT FidCarNumber, FName,Fage FROM  dbo. T_TempEmployee
--默认情况下,union合并了俩个查询结果集 ,当中全然反复的数据行被合并为一条假设须要在联合结果集中返回全部的
--记录而不管他们是否唯一 ,则须要在union 后使用all 比方以下
SELECT fnumber, fname,Fage FROM dbo. T_Employee
UNION ALL
SELECT FidCarNumber, FName,Fage FROM  dbo. T_TempEmployee

--联合结果集在制作报表的时候常常被用到 ,我们能够使用联合结果集将没有直接关系的数据显示到同一张报表中
--被连接的的俩个SQL 语句能够是非常复杂的也能够使非常easy的仅仅要符合 union的俩个规则就好了
--范例员工年龄报表要求查询员工的最低年龄和最高年龄 ,暂时工和公式工要分开查询
SELECT ' 正式员工最高年龄 ',max (Fage) from T_Employee
UNION
SELECT ' 正式员工最低年龄 ',min (Fage) from T_Employee
UNION
SELECT ' 暂时工员工最高年龄 ',max (Fage) from T_TempEmployee
UNION
SELECT ' 暂时员工最低年龄 ',min (Fage) from T_TempEmployee
--正式员工工资报表要求查询每位正式员工的信息 ,工号, 工资并在最后一行加上全部员工工资的合计
select FName, FSalary From T_Employee
UNION
SELECT ' 工资合计', sum(FSalary ) from T_Employee



--建表语句
GO
/****** 对象:  Table [dbo].[T_Person2]    脚本日期: 07/03/2015 13:52:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[T_Person2] (
      [FIdNumber] [varchar] (20) NULL,
      [FName] [varchar] (20) NULL,
      [FBirthDay] [datetime] NULL,
      [FRegDay] [datetime] NULL,
      [FWeight] [decimal] (10, 2) NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF


123456789120      Tom   1981 /3/ 22 0:00 :00 1998/ 5/1 0 :00: 00  56.67
123456789121      Jim   1987 /1/ 18 0:00 :00 1999/ 8/21 0 :00: 00 36.17
123456789122      Lily  1987 /11/ 8 0:00 :00 2001/ 9/18 0 :00: 00 40.33
123456789123      Kelly 1982 /7/ 12 0:00 :00 2000/ 3/1 0 :00: 00  46.23
123456789124      Sam   1983 /2/ 16 0:00 :00 1998/ 5/1 0 :00: 00  48.68
123456789125      Kerry 1984 /8/ 7 0:00 :00  1999/ 3/1 0 :00: 00  66.67
123456789126      smith 1980 /1/ 9 0:00 :00  2002/ 9/23 0 :00: 00 51.28
123456789127      BillGates   1972 /7/ 18 0:00 :00 1995/ 6/19 0 :00: 00 60.32
NULL  NULL   NULL   NULL  NULL

--SQL 标准中仅仅规定了个数学函数 ,只是非常多主流数据库系统都提供了大量常常使用的数学函数 ,
--并且差点儿全部的数据库都提供了支持
--求绝对值ABS() 返回一个数值的绝对值 ,该函数接受一个參数,这个參数为待求绝对值的表达式
SELECT FWeight- 50,ABS (FWeight), ABS(-5.38 )  FROM dbo.T_Person2

--power()函数是用来计算指数的函数该函数接受俩个參数 ,一个为參数为待求幂的表达式 ,第二參数为幂
SELECT FWeight,POWER( FWeight,-0.5 ),POWER( FWeight,2 ),POWER( FWeight,3 ),POWER( FWeight,4 )  FROM dbo.T_Person2

--sqrt()函数是用来计算求平方根的函数该函数接受一个參数 ,这个參数为待计算平方根的表达式
SELECT FWeight, SQRT(FWeight ) FROM T_Person2

--rand() 随机数函数另外还有带參方法提供随机数种子
SELECT RAND ()

--ceiling()舍入到最大整数 这个函数用来舍掉一个数的小数点的后部分并且向上舍入到邻近的最大整数
--比方舍入为4  2.89被舍入为 3   -3.63 舍入为-3  不是-4 注意向上取整
select FWeight, CEILING(FWeight ),CEILING( FWeight*-1 ) FROM T_Person2

--floor() 和ceiling() 相反向下舍入到邻近的最小整数
--比方舍入为3  2.89舍入为     -3.63 舍入为-4 
select FWeight, FLOOR(FWeight ),FLOOR( FWeight*-1 ) FROM T_Person2

--round()函数用来进行四舍五入提供俩个參数 ,和单一參数的使用方法
--round(m,d) 当中m 为待进行四舍五入的数值而 d则为计算精度,也就是进行四舍五入时保留的小数位数
--比方进行精度为四舍五入为 3.66;3.32122 进行精度为四舍五入为3.321;
--当d 为时,表示不保留小数位数进行四舍五入 3.663 为4;-2.223 为-2;
--特别值得注意的是d 还能够设置为负数这时表示在整数部分进行四舍五入
--比方进行精度为 得到 ; 233.7 进行精度为得到200;3321.22 进行精度为 得到3300;
--单一參数相当与于把d默认看出就好了 MS SQLSERVER 和DB2 上并不支持单一參数
SELECT FName,FWeight, ROUND(FWeight ,1), ROUND(FWeight *-1, 0),ROUND (FWeight,- 1) FROM T_person2

--这些函数我个人觉得用到次数不是非常多案例就直接略过 ,举例下用到再补充
--正弦函数sin()
--余弦函数cos()
--求反正弦函数asin()
--求反余弦值函数acos()
--求正切值tan()
--求反正切值atan()
--求余切cot()
-- π值PI() 
SELECT PI ()
--弧度制转换为角度制degrees()
--角度制转换为弧度制radlans()
--求符号sign()  假设大于返回 1;等于返回; 小于返回;
--求整除余数mysql 和 oracl 提供了Mod() 函数;Ms sql 提供了 "%"能够直接使用
select FWeight, FWeight%5 FROM T_person2
--求自然数对数log()
--求以为底的对数log10()
--求幂power(x,y) 用来计算x 的 y 次幂


--计算字符串长度
SELECT FName, LEN(FName ) FROM T_Person2

--字符串转化为小写LOWER()
SELECT FName, LOWER(FName ) FROM T_Person2

--字符串转化为大写upper()
SELECT FName, upper(FName ) FROM T_Person2

--截取字符串左側空格ltrim()
--截取字符串右側空格rtrim()
--截取字符串俩側空格trim() MSSQL中不支持要用上面俩个函数组合实现

--截取字符串substring(String,start_position,length) 跟C# 语法一样
SELECT SUBSTRING ('123456789', 2,3 )

--查询子字符在主字符串是否存在及位置 [charindex](expression1, expression2, [[start_location]])
--expression1 要查询的字符串,子字符 ;expression2主字符串;[start_location] 開始搜寻位置
 SELECT FName,CHARINDEX( FName,'m' ,0), CHARINDEX(FName ,'m'), CHARINDEX('m' ,FName) FROM T_Person2
 
 --从左側截取子字符串 substring() 类似的函数leef(string,length)
 --从右側截取字符串   right(String,length)
 
 --字符串替换 replace(string,string_tobe_replace,string_to_replace)
 --string 原字符串 ;string_tobe_replace须要替换的字符串;用什么字符去取代原字符
 SELECT REPLACE('123456789' ,'45', '77')
 
 
 --得到字符的 ASCII码ASCII('char') 注意仅仅能是单个字符假设是字符串的话 ,得到是首字母的ASCII码
 SELECT ASCII('b' ),ASCII( 'bac')
 
 --与 ASCII码相反的函数,依据数字反向获取这个数字的 ASCII码char()
 SELECT CHAR(98 )
 
 --发音匹配度 ,假设做输入法,或者模糊查询之类也许用的到 soundex()
 SELECT SOUNDEX('jack' ),SOUNDEX( 'jeck'),SOUNDEX ('joke'), SOUNDEX('juke' ),SOUNDEX( 'look'),SOUNDEX ('jobe')
 --还有一个关于发音类似度函数 ,由于发音特征值含义非常复杂 ,difference(),俩简化俩个字符串的发音比較返回
 --来反应俩个字符的类似度数字越小越接近是不是用这个结合下拉框选择项是不是非常给力
 SELECT FName ,DIFFERENCE( FName,'Kerry' ) FROM T_Person2
 


 --MySql Ms Sqlserver 和 DB2中能够用字符串表示日期时间类型 ,数据库系统会自己主动在内部将他们转换为日期时间类型
 --取得当前日期函数 GETDATE() 能够看到返回信息包括了日期 ,时间, 精确到秒以后的时间戳信息
 --Ms SQL server并没有专门提供取得当前日期 ,时间的函数,只是我们能够将 GETDATE()的返回值进行处理
 --须要借助 CONVERT()函数
 SELECT GETDATE() AS 当前时间
 SELECT CONVERT(VARCHAR (50), GETDATE(),101 ) AS 当前日期
 SELECT CONVERT(VARCHAR (50), GETDATE(),108 ) AS 当前时间
 
 --MS SQL 提供 DATEADD()函数用于进行日期时间的加法运算
 --dateadd(datepart,numnber,date)
 --date为待计算的日期 ;參数datepart 指定要返回新值的日期的组成部分 ,须要计算的部分;
 --number 计算值
 SELECT DATEADD(day ,3, '2015-7-20 11:20:56')
 
 --计算每一个人出生后年 (year),20季度(quarter),68 个月(month)以及周 (week)前的日子
SELECT FBirthDay,DATEADD( YEAR,3 ,FBirthDay), DATEADD(quarter ,20, FBirthDay),
DATEADD(MONTH ,68, FBirthDay),DATEADD (week,- 1000,FBirthDay )
FROM T_Person2

--计算日期差额,比方计算回款日 ,验收日之间的天数,检索最后一次登录日期大于天的用户
--MS SQL 提供了DATEDIFF() 计算指定差额 datediff(datepart,startdate,enddate)
--datepart单位( 參考表格)  startdate開始日期 enddate结束日期
SELECT FRegDay, FBirthDay,DATEDIFF (week, FBirthDay,FRegDay ) FROM T_Person2


--计算一个日期是星期几(比方安排报道日期为周末 ,则须要向后顺延)
--MS SQL 提供了dateName(datepart,date)  datepart 要返回日期參数 ,要返回周就是(week)
--可选參数如图
SELECT FRegDay, DATENAME(dw ,FRegDay), FBirthDay,DATENAME (dw, FBirthDay) FROM T_Person2

--DATENAME 也能够用来取得日期的指定部分诸如月份年份时分秒等
--还有一个函数是datepart(datepart,date)
--尽管俩个函数都能提取日期的特定部分 ,可是datepart() 返回值为数值 ,而dateName 函数则会尽可能的
--以名称方式返回返回值
SELECT FRegDay,datepart( dayofyear,FRegDay ),FBirthDay, DATENAME(year ,FBirthDay) FROM T_Person2


--类型转换函数
--系统计算时会自己主动将字符串转为整数类型 ,这种转换为隐式转换有时候不能自己主动转换 ,
--我们须要手动显示转换;显示转换不仅能够保证类型转换的正确性 ,并且还能够提供数据
--的处理速度,因此应该尽量使用显示转换 ,避免使用隐式转换
-- MS SQL 提供cast() convert() 俩个类型进行转换 ,
-- cast(expression as data_type) 符合ANSI SQL 99的函数 ;
-- convert(date_type,expression) 是符合ODBC标准的函数
SELECT CAST ('-30' AS INT),CONVERT (DECIMAL, '3.1415726'),CONVERT (DATETIME, '2015-7-21 11:28:24')

--将每一个人的身份证后位转换为整数类型并进行相关计算
SELECT FIdNumber,RIGHT( FIdNumber,3 ) AS 后位, cast(RIGHT(FIdNumber ,3) as int) as 后位整数
,cast(RIGHT( FIdNumber,3 ) AS INT)+ 1 AS 后位加
,CAST(RIGHT( FIdNumber,3 ) AS INT)/ 2 AS 后位除以
 FROM T_Person2
 
 
 --空值处理
 --假设名称为空则返回别名 ,或者特定值
 --coalesce(expression,value1,value2,...,valuen)函数
 --推断 expression是否为空, 不为空则正常显示 ,假设为空则用value1取代 ,
 --假设 value1也为空则用,value3取代以此类推
SELECT FBirthDay, FRegDay,COALESCE (FBirthDay, FRegDay,'2008-08-08' ),
COALESCE(FRegDay ,'1990-06-05')
FROM T_Person2

--空值处理的还有一个函数isnull(expression,value)算是 coalesce的简化版
SELECT FBirthDay, FRegDay,ISNULL (FBirthDay, FRegDay),
ISNULL(FRegDay ,'1990-06-05')
FROM T_Person2

--nullIf(expression1,expression2)
--假设俩个表达式不等价,则返回第一个 expression1的值, 假设等价,则返回第一个
--expression1类型的空值
SELECT FBirthDay, FRegDay,nullIf (FBirthDay, FRegDay)
FROM T_Person2

--流程控制函数case()
--假设年龄大于返回姓名,否则返回别名
--CASE experession
--WHEN value1 THEN returnValue1
--WHEN value2 THEN returnValue2
--WHEN value3 THEN returnValue3
--ELSE defaulretunValue
--end
--类似于编程中的switch...case
--假设FName 叫Tom则返回 GoodBoy,叫Jim 则返回GoodGril,Lily返回 badBoy,
--Kelly返回badGrill, 其它返回Normal
SELECT FName,( CASE FName
WHEN 'Tom' THEN 'GoodBoy'
WHEN 'Jim' THEN 'GoodGril'
WHEN 'Lily' THEN 'badBoy'
WHEN 'Kelly' THEN 'badGrill'
ELSE 'Normal'
END) FROM T_Person2

--使用方法
--上面的case 语句仅仅能用于相等情况下的 ,假设要推断,年龄小于则返回未成年
--否则返回成年,就非常乏力须要用到 case()还有一种使用方法
--CASE
--WHEN condition1 THEN returnValue1
--WHEN condition2 THEN returnValue2
--WHEN condition3 THEN returnValue3
--....
--ELSE defaultReturnValue
--END
--当中condition1,condition2,condition3 为条件表达式 ,假设condition1 为真,
--则返回returnValue1; 否则运行条件 ,假设condition2 为真则返回 returnValue2,
--否则运行条件condition3 不符合上面的条件则返回默认值 defaultReturnValue

--来推断一个人体重假设小于则为太瘦
--来推断一个人体重假设大于则觉得太胖
--40~50为正常
SELECT FName, FWeight,(CASE WHEN FWeight <40 THEN 'thin' WHEN FWeight> 50
THEN 'fat' ELSE 'OK' END )
 FROM T_Person2
 
 --MS SQL 独有函数
 --patindex('%pattern',expression) 值匹配, 获取指定字符 ,在目标字符中的位置;
 --更官方的说明 :用来计算字符串中指定表达式的開始位置 ,确定值匹配
--查找姓名中包括m 出现的位置
 SELECT FName ,PATINDEX( '%_m%',FName ) FROM T_Person2
 
--获取字符串反复N次后的字符串 replicate(str,count) 字面意思复制
select Fname, replicate(FName ,2) FROM T_Person2
--字符串颠倒reverse()
SELECT FName, REVERSE(Fname ) FROM T_Person2

--isDate(expression) 用来确定输入的表达式是否为有效日期推断日期的合法的函数
--假设推断是日期则返回不是日期格式则返回
SELECT ISDATE ('ZZZZZ'), ISDATE('2015-7-21 16:17:54' ),ISDATE( '2015080A'),
ISDATE('20150606' )

--isnumeric(expression) 函数用来确定表达式是否为有效的数值类型
--假设输入的表达式为有效整数 ,浮点数money 或者decimal类型时 ,返回, 否则返回
SELECT ISNUMERIC('str' ),ISNUMERIC(NULL), ISNUMERIC('0.234' ),ISNUMERIC( '-30')

--辅助功能函数
--app_name()函数返回当前会话的应用程序名称 ;
--current_user  注意这个函数不带括号调用返回当前用户的登录名
--host_name() 返回工作站名
SELECT APP_NAME (),CURRENT_USER, HOST_NAME()

--生成全局唯一字符串函数 newId()
SELECT NEWID (),NEWID()



--利用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_name

 --非空约束
 --在定义数据库的时候 ,默认情况下全部字段都是同意为空值的 ,
 --假设须要在创建表的时候显示指定禁止一个字段为空的方式就是
 --在字段定义后添加 not null, 范比例如以下
 --CREATE TABLE T_notNull(Fnumber VARCHAR(20) NOT NULL,FName VARCHAR(20),FAge INT)

--唯一约束
--唯一约束又称为unique约束 ,它用于防止一个特定的列中俩个记录具有相同的值
--设置方式就是在字段定义后添加 unique
--CREATE TABLE T_UniqueTest(Fnumber VARCHAR(20) UNIQUE,FName VARCHAR(20),Fage INT)

--check约束
--check约束会检查输入到记录中的值是否满足一个条件 ,假设不满足这个条件则
--对数据库的改动不会成功
--比方一个人年龄不可能是负数 ,一个人的入学日期不可能早于出身日期 ,出厂月份
--不可能大于月能够在check条件中使用随意有效的 SQL表达式,check 约束对于插入 ,
--更新等随意对数据改动的操作都进行检查
--具体需求的check约束 ,依据需求百度,我开发至今都不怎么去使用 check,一方面客户
--不停的变更会不停的挑战 check,导致改动频繁,不有用測试数据插入变得麻烦
--check约束范例
CREATE TABLE CHECKTABLE(Fid INT,Fname VARCHAR(20 ),
Fage VARCHAR( 20) CHECK(Fage >0),
FWorkYear INT CHECK ( FWorkYear>0 ))

--主键约束
--由于每张表都要有主键,因此主键约束是非常重要的 ,并且主键约束是外键关联的基础
--主键约束为表之间的关联提供了链接点
--主键必须能够唯一标识一条记录 ,也就是主键字段中的值必须是唯一的 ,并且不能包括
--NULL值从这种意义来说,主键约束是 unique约束和非空约束的组合尽管一张表中能够
--有多个unique 约束和非空约束可是每一个表却仅仅能有一个主键约束
--字段后面添加primary key
--主键约束范例:
CREATE TABLE PrimaryTable(Fid INT PRIMARY KEY, Fname VARCHAR( 20))

--外键约束
--当一些信息在表中反复出现的时候 ,我们就要考虑将他们提取到另外一张表中 ,
--然后在源表中引用新创建的表中的数据比方非常多作者都有不止一本著作 ,所以
--在保存书籍信息的时候,应该把作者信息放到单独的一张表 (然后把作者ID放到书籍表中 )
--范例格式:  foreign key 外键字段references 外键表名 (外键表的主键字段)
--比方以下的SQL语句就是加入了外键约束 T_Author 表和T_Book 表的创建语句
CREATE TABLE T_AUTHOR(Fid VARCHAR(20 ) PRIMARY KEY, FName VARCHAR( 100)
,Fage INT ,FEmail VARCHAR (20));
CREATE TABLE T_BOOK(Fid VARCHAR(20 ) PRIMARY KEY, FName VARCHAR( 20)
,FPageCount INT ,FAuthorId VARCHAR (20)
,FOREIGN KEY ( FAuthorId) REFERENCES T_AUTHOR( Fid))

--表连接
--建表及測试数据
--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 ) NOT NULL
,FPrice NUMERIC (10, 2),FCustomerId INT,FTypeId INT,PRIMARY KEY( Fid))

CREATE TABLE T_OrderType(Fid INT NOT NULL,FName VARCHAR(20 ) NOT NULL
,PRIMARY KEY(Fid ))

INSERT INTO T_Customer(Fid ,FName, Fage)
VALUES(1 ,'Tom', 21)
INSERT INTO T_Customer(Fid ,FName, Fage)
VALUES(2 ,'MIKE', 24)
INSERT INTO T_Customer(Fid ,FName, Fage)
VALUES(3 ,'JACK', 30)
INSERT INTO T_Customer(Fid ,FName, Fage)
VALUES(4 ,'Tom', 25)
INSERT INTO T_Customer(Fid ,FName, Fage)
VALUES(5 ,'LINDA',NULL)

INSERT INTO T_OrderType(Fid ,FName)
VALUES(1 ,'MarketCrder')
INSERT INTO T_OrderType(Fid ,FName)
VALUES(2 ,'LimitOrder')
INSERT INTO T_OrderType(Fid ,FName)
VALUES(3 ,'Stop Order')
INSERT INTO T_OrderType(Fid ,FName)
VALUES(4 ,'StopLimit Order')

INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(1 ,'K001', 100,1 ,1)
INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(2 ,'K002', 200,1 ,1)
INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(3 ,'T003', 300,1 ,1)
INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(4 ,'N002', 100,2 ,2)
INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(5 ,'N003', 500,3 ,4)
INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(6 ,'T001', 300,4 ,3)
INSERT INTO T_Order(Fid ,FNumber, FPrice,FCustomerId ,FTypeId)
VALUES(7 ,'T002', 100,NULL,1 )

--JOINkeyword将一个或者多个表依照彼此间的关系连接为一个结果集
--inner join 内连接组合俩张表,并且基于俩张表的关联来联系他们
--使用内连接须要指表中哪些字段成关联关系 ,并且须要指定基于什么
--条件进行连接内连接语法 inner join  table_name  on condition
--大多数系统中,inner join中的 inner是可选的,inner join 是默认的链接方式
SELECT * FROM T_Order
SELECT * FROM T_Customer
select * FROM T_Order INNER JOIN T_Customer
ON T_Customer. Fid = T_Order .Fid

--在使用表连接的时候,能够不局限于仅仅连俩张表 ,由于在非常情况下须要
--连接很多表
SELECT * FROM T_Order
SELECT o. Fid, o .FNumber, o.FPrice ,c. FName, ot .FName
from T_Order AS o INNER JOIN T_Customer AS c
ON o. FCustomerId = c .Fid
INNER JOIN T_OrderType AS ot
ON o. FTypeId = ot .Fid

--不等值连接
--上面演示的在on后面设置某字段必须等于还有一个表中的字段
--除了等值连接,还存在一种不等值连接也就是在连接的条件中能够使用
--小于(<) 、大于(>)、不等于 (<>)等于运算, 并且还能够使用 like
--,between and等甚至还能够使用函数
SELECT o. Fid, o .FNumber, o.FPrice ,c. FName
from T_Order AS o INNER JOIN T_Customer AS c
ON o. FPrice < c .Fage * 5
--在能够在等值连接后面加入 and  来加入限制
AND o. FCustomerId = c .Fid

--交叉连接
--与内连接比起来,交叉连接非常easy ,由于它不存ON子句
--交叉连接会将涉及到的全部记录都包括在结果集中能够採用俩种方式
--来定义交叉连接,各自是隐私连接和显示的连接
SELECT * FROM T_Order --7条数据
SELECT * FROM T_Customer --5条数据
SELECT * FROM T_Customer ,T_Order--35 条数据= 7*5
SELECT * FROM T_Customer
CROSS JOIN T_Order --显示连接 ;隐式连接默认忽略CROSS JOIN

--自连接
--上面讲的都是在不同数据表之间进行的 ,事实上參与连接的表全然能够是
--同一张表, 也就是表与其自身的连接 ,这种连接就被称为自连接
SELECT t1.*, t2.* FROM T_Customer  t1 INNER JOIN
T_Customer AS t2 ON t2. Fid = t1 .Fid


--外部连接
--左外部连接left outer join  右外部连接 right outer join
--全外部连接full outer join
--外部连接的语法和内部连接差点儿一样 ,主要差别就是对于空值的处理
--外部连接不须要俩个表具有匹配记录 ,这样能够指定某个表中的记录总是放
--到结果集中

--左外部连接以左表为基准去匹配数据 ,将左表的数据放到结果集中 ,
--不管是否在右表中存在匹配记录
--,能匹配到则显示,不能匹配则显示为 NULL
SELECT * FROM T_Order --7条数据
SELECT * FROM T_Customer --5条数据
select o. FNumber, o .FPrice, o.FCustomerId , c. FName, c .Fage
  FROM T_Order AS o LEFT OUTER JOIN T_Customer AS c
ON o. FCustomerId =c .Fid

--右外部连接以右表为基准去匹配数据 ,将右表的数据放到结果集中 ,
--不管是否在左表中存在匹配记录
--,能匹配到则显示,不能匹配则显示为 NULL
SELECT * FROM T_Order --7条数据
SELECT * FROM T_Customer --5条数据
select o. FNumber, o .FPrice, o.FCustomerId , c. FName, c .Fage
  FROM T_Order AS o RIGHT OUTER JOIN T_Customer AS c
ON o. FCustomerId =c .Fid

--全外部连接
--差点儿全部的数据库都支持左外部连接和右外部连接 ,可是全外部连接
--则不是全部数据库都支持的 ,诸如MYsql.
--全外部连接是左外部连接和右外部连接的合集 ,由于即使在右表中不存
--在匹配连接条件的数据,左表中的全部记录也将被放到结果集中 ,相同
--左表中不存在匹配记录,右表中的全部记录也将被放到结果集中
select o. FNumber, o .FPrice, o.FCustomerId , c. FName, c .Fage
  FROM T_Order AS o Full OUTER JOIN T_Customer AS c
ON o. FCustomerId =c .Fid


--子查询
--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


--范例列值子查询
--PS:假设在子查询中使用别名 ,在引用它的时候,也用别名
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 keyword符前 ,所比較的值也需求匹配子查询中的随意值
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



---开窗函数
--測试数据及表
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,
      [FCity] [varchar] (20) NULL,
      [FAge] INT,
      FSalary INT
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Tom' ,'BeiJing', 20,3000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Tim' ,'ChengDu', 21,4000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Jim' ,'BeiJing', 22,3500 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Lily' ,'LonDon', 21,2000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('John' ,'NewYork', 22,1000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('YaoMing' ,'BeiJing', 20,3000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Swing' ,'LonDon', 22,2000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Guo' ,'NewYork', 20,2800 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('YuQian' ,'BeiJing', 24,8000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Ketty' ,'London', 25,8500 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Merry' ,'BeiJing', 23,3500 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Smith' ,'ChengDu', 30,3000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Bill' ,'BeiJing', 25,2000 )

INSERT INTO T_Person3(FName ,FCity, FAge,FSalary )
VALUES('Jerry' ,'NewYory', 24,3300 )


SELECT * FROM T_Person3
--与聚合函数一样,开窗函数也是对行集组进行聚合计算
--可是它不像普通聚合函数那样每组仅仅返回一个值 ,开窗函数能够
--为每组返回多个值,由于开窗函数所运行聚合计算的行集组是窗
--口ISO SQL 规定了这种函数为开窗函数 ,在oracle 中则被称为
--分析函数, 而在DB2中则被称为 OLAP函数
SELECT COUNT (*) FROM T_Person3

--以下俩个表达是一个意思
SELECT FCity, FAge,COUNT (*) OVER () FROM T_Person3

SELECT FCity, FAge,COUNT (*) FROM T_Person3
WHERE FSalary < 5000
GROUP BY FCity,FAge

--OVERkeyword表示把函数当成开窗函数而不是聚合函数
--SQL标准同意将全部聚合函数用做开窗函数 ,使用OVER keyword来
--区分这俩种使用方法
--上面中count(*)over() 对于查询结果的每一行都返回全部符合
--条件的行的条数OVER()keyword后的括号里还常常加入选项 ,用以
--改变进行聚合运算的窗体范围假设 OVER()keyword后面的括号里的
--选项为空, 则开窗函数会对结果集中的全部行进行聚合运算


--partition by 子句
--开窗函数over() keyword后的括号里 ,能够使用partition by 子句
--来定义行的区分,从而进行聚合计算与 group by子句不同,
--partition by子句创建的分区是独立于结果集的 ,创建的分区仅仅是
--提供聚合计算的并且不同的开窗函数所创建的分区也互不影响
--范例以下SQL 用于显示每一个人员的信息及所属城市的人员数
SELECT FName, FCity, FAge ,FSalary,
COUNT(*) OVER ( PARTITION BY FCity)
FROM T_Person3
--同一个SQL 语句中能够使用多个开窗函数 ,并且这些开窗函数并不会
--相互干扰
--范例
SELECT FName, FCity, FAge , FSalary,
COUNT(*) OVER ( PARTITION BY FCity),
COUNT(*) OVER ( PARTITION BY FAge)  FROM t_Person3

--MS SQL 并不支持order by 子句的开窗函数 ;


--with子句与子查询
--一次定义多次使用用于提取子查询
WITH
SSSS AS
(
       SELECT FAge FROM T_person3 WHERE FAge <24
)

SELECT * FROM T_person3 AS t WHERE T.FAge IN ( SELECT * FROM SSSS )
--374


with
cr as
 (
     select FAge from T_person3
 )

 select * from T_person3 where FAge in ( select * from cr )
  


原文地址:https://www.cnblogs.com/lxjshuju/p/6940457.html