基础的SQL语句

时间:2022-08-21 20:01:37

一、SQL基础知识

1DDL(数据定义语言)

1)创建数据表

--创建数据表

createtable Test(Idint not null, Agechar(20))

 

--创建数据表

createtable T_Person1(Idint not null,

Name nvarchar(50),

Ageint null)

 

 

 

--创建表,添加外键

Createtable T_Students(

StudentNochar(4),

CourseNochar(4),

Scoreint,

Primarykey(StudentNo),

Foreignkey(CourseNo)References T_Course(CourseNo)

);

 

2)修改表结构

--修改表结构,添加字段

Altertable T_Personadd NickName nvarchar(50)null;

 

--修改表结构,删除字段

Altertable T_PersonDrop NickName;

 

3)删除数据表

--删除数据表

Droptable T_Person;

 

--删除数据表

droptable test

4)创建索引

Create[Unique]Index <索引名>on <基本表名>(<列明序列>);

 

2DML(数据操纵语言)

1)插入语句

insertinto T_Person1(Id,Name,Age)values(1,'Vicky',20)

--插入一条据数,字段和值必须前后对应

insertinto T_Preson1(Id,Name,Age)values(2,'Tom',19)

insertinto T_Person1(Id,Name,Age)values(4,'Jim',19)

insertinto T_Person1(Id,Name,Age)values(5,'Green',20)

insertinto T_Person1(Id,Name,Age)values(6,'Hanmeimei',21)

insertinto T_Person1(Id,Name,Age)values(7,'Lilei',22)

insertinto T_Person1(Id,Name,Age)values(8,'Sky',23)

 

insertinto T_Person1(Id,Name,Age)values(newid(),'Tom',19)

 

2)更新语句

--修改列,把所有的age字段改为30

update T_Person1set age=30

 

--把所有的Age字段和Name字段设置为...

update T_Person1set Age=50,Name='Lucy'

 

 

update T_Person1set Name='Frankie'where Age=30

 

update T_Person1set Name=N'中文字符'where Age=20

--中文字符前面最好加上N,以防出现乱码

 

update T_Person1set Name=N'成年人'where Age=30or Age=50

 

3)删除语句

deletefrom T_Person1

--删除表中全部数据

 

deletefrom T_Person1where Name='Tom'

--根据条件删除数据

 

4)查询语句

查询语句非常强大,几乎可以查任意东西!

-----------------

----数据检索 -----

-----------------

--查询不与任何表关联的数据.

SELECT1+1; --简单运算
select
1+2 as
结果

 

SELECTnewid();--查询一个GUID字符创

 

selectGETDATE()as 日期--查询日期

 

--可以查询SQLServer版本

select @@VERSIONas SQLServer版本

 

--一次查询多个

select1+1 结果,GETDATE()as 日期, @@VERSIONas 版本,NEWID()as 编号

 

 

--简单的数据查询.HelloWorld级别

SELECT* FROM T_Employee;

 

--只查询需要的列.

SELECT FNumberFROM T_Employee;

 

--给列取别名.As关键字

SELECT FNumberAS 编号, FNameAS 姓名FROM T_Employee;

 

--使用 WHERE查询符合条件的记录.

SELECT FNameFROM T_EmployeeWHERE FSalary<5000;

 

--对表记录进行排序,默认排序规则是ASC

SELECT* FROM T_Employee ORDER BY FAgeASC,FSalaryDESC;

 

--ORDER BY子句要放在 WHERE子句之后.

SELECT* FROM T_Employee WHERE FAge>23ORDER BY FAge DESC,FSalaryDESC;

 

--WHERE中可以使用的逻辑运算符:orandnot<>=>=<=!=<>.

 

--模糊匹配,首字母未知.

SELECT* FROM T_Employee WHERE FName LIKE'_arry';

 

--模糊匹配,前后多个字符未知.

SELECT* FROM T_Employee WHERE FName LIKE'%n%';

 

--NULL表示"不知道",有 NULL参与的运算结果一般都为 NULL.

 

--查询数据是否为 NULL,不能用 = != <>,要用IS关键字

SELECT* FROM T_Employee WHERE FName ISNULL;

SELECT* FROM T_Employee WHERE FName ISNOT NULL;

 

--查询在某个范围内的数据,IN表示包含于,IN后面是一个集合

SELECT* FROM T_Employee WHERE FAge IN(23,25,28);

 

--下面两条查询语句等价。

SELECT* FROM T_Employee WHERE FAge>=23AND FAge<=30;

SELECT* FROM T_Employee WHERE FAge BETWEEN23 AND 30;

 

----创建一张Employee表,以下几个Demo中会用的这张表中的数据

----SQL管理器中执行下面的SQL语句,在T_Employee表中进行练习

createtable T_Employee(FNumbervarchar(20),

FNamevarchar(20),

FAgeint,

FSalaryNumeric(10,2),

primarykey (FNumber)

)

 

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('DEV001','Tom',25,8300)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('DEV002','Jerry',28,2300.83)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('SALES001','Lucy',25,5000)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('SALES002','Lily',25,6200)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('SALES003','Vicky',25,1200)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('HR001','James',23,2200.88)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('HR002','Tom',25,5100.36)

insertinto T_Employee(FNumber,FName,FAge,FSalary)values('IT001','Tom',28,3900)

insertinto T_Employee(FNumber,FAge,FSalary)values('IT002',25,3800)

 

--开始对T_Employee表进行各种操作

--检索所有字段

select* from T_Employee

 

--只检索特定字段

select FName,FAgefrom T_Employee

 

--带过滤条件的检索

select* from T_Employee

where FSalary<5000

 

--可更改显示列名的关键字asas—起别名

select FNameas 姓名,FAgeas 年龄,FSalaryas 薪水from T_Employee

 

 

二、SQLServer 中的数据类型

1精确数字类型

bigint

int

smallint

tinyint

bit

money

smallmoney

2字符型数据类型MS建议用VarChar(max)代替Text

Char

VarChar

Text

3近似数字类型

Decimal

Numeric

Real

Float

4Unicode字符串类型

Nchar

NvarChar

Ntext

5二进制数据类型,MS建议VarBinary(Max)代替Image数据类型,max=231-1

Binary(n)存储固定长度的二进制数据

VarBinary(n)存储可变长度的二进制数据,范围在n~(1,8000)

Image存储图像信息

6日期和时间类型,数据范围不同,精确地不同

DateTime

SmallDateTime

7特殊用途数据类型

Cursor

Sql-variant

Table

TimeStamp

UniqueIdentifier

XML

 

三、SQL中的内置函数

 

--------------------------------------

-----数据汇总-聚合函数 ---------

--------------------------------------

--查询T_Employee表中数据条数

selectCOUNT(*)from T_Employee

 

--查询工资最高的人

selectMAX(FSalary)as Top1 from T_Employee

 

--查询工资最低的人

selectMin(FSalary)as Bottom1 from T_Employee

 

--查询工资的平均水平

selectAvg(FSalary)as 平均水平from T_Employee

 

--所有工资的和

selectSUM(FSalary)as 总工资from T_Employee

 

--查询工资大于5K的员工总数

selectCOUNT(*)as total from T_Employee

where FSalary>5000

 

 

------------------------------

-----数据排序 -------

------------------------------

--按年龄排序升序,默认是升序

select* from T_Employee

orderby FAge ASC

 

--多个条件排序,先什么,后什么,在前一个条件相同的情况下,根据后一个条件进行排列

--whereorder by之前

select* from T_Employee

orderby FAge ASC, FSalaryDESC

 

 

------------------------------

-----模糊匹配 -------

------------------------------

--通配符查询

--1.单字符通配符_

--2.多字符通配符%

--DEV开头的任意个字符串

select* from T_Employee

where FNumberlike 'DEV%'

 

--以一个字符开头,om结尾的字符串

select* from T_Employee

where FNamelike '_om'

 

--检索姓名中包含m的字符

select* from T_Employee

where FNamelike '%m%'

 

 

------------------------------

-----空值处理 -------

------------------------------

--null表示不知道,不是没有值

--null和其他值计算结果是null

selectnull+1

 

--查询名字是null的数据

select* from T_Employee

where FNameis null

 

--查询名字不为空null的数据

select* from T_Employee

where FNameis not null

 

--年龄是23,25,28中的员工

select* from T_Employee

where FAge=23or FAge=25or FAge=28

 

 

--或者用in集合查询

--年龄是23,25,28中的员工

select* from T_Employee

where FAgein (23,25,28)

 

--年龄在2025之间的员工信息

select* from T_Employee

where FAge>20and FAge<25

 

--年龄在2025之间的员工信息,包含25

select* from T_Employee

where FAgebetween 20 and25

 

 

------------------------------

-----数据分组 -------

------------------------------

Select FAge,COUNT(*)from T_Employee

groupby FAge

--1.根据年龄进行分组

--2.再取出分组后的年龄的个数

 

--注意:没有出现在group by 子句中的字段,不能出现在select语句后的列名列表中(聚合函数除外)

--group by必须出现在where后面

Select FAge,AVG(FSalary),COUNT(*)from T_Employee

groupby FAge

 

--错误用法

Select FAge,FName,COUNT(*)from T_Employee

groupby FAge

 

--加上wheregroup by 子句

--group by必须出现在where后面

Select FAge,AVG(FSalary),COUNT(*)from T_Employee

where FAge>=25

groupby FAge

 

 

--Having不能包含查不到的字段,只能包含聚合函数和本次查询有关的字段

select FAge,COUNT(*)from T_Employee

groupby FAge

HavingCOUNT(*)>1

 

select FAge,COUNT(*)from T_Employee

where FSalary>2500

groupby FAge

 

--HAVING子句中的列 'T_Employee.FSalary'无效,因为该列没有包含在聚合函数或 GROUP BY子句中

--Having是对分组后信息的过滤,能用的列和select中能有的列是一样的。

--因此,having不能代替where

select FAge,COUNT(*)from T_Employee

groupby FAge

Having FSalary>2500

 

 

------------------------------

-----确定结果集行数 -------

------------------------------

--取出所有员工的信息,根据工资降序排列

select* from T_Employee

orderby FSalary DESC

 

--取出前三名员工的信息,根据工资降序排列

select top3 * from T_Employee

orderby FSalary DESC

 

--根据工资取出排名在6-8的员工信息,按工资降排列

select top3 * from T_Employee

where FNumbernot in

(select top5 FNumber from T_Employee order by FSalaryDESC)

orderby FSalary DESC

 

 

 

---修改数据表,添加字段,更新字段的值等操作。

altertable T_Employeeadd FSubCompanyvarchar(20)

altertable T_Employeeadd FDepartmentvarchar(20)

update T_Employeeset FSubCompany='Beijing',FDepartment='Development'

where FNumber='DEV001';

update T_Employeeset FSubCompany='ShenZhen',FDepartment='Development'

where FNumber='DEV002';

update T_Employeeset FSubCompany='Beijing',FDepartment='HumanResource'

where FNumber='HR001';

update T_Employeeset FSubCompany='Beijing',FDepartment='HumanResource'

where FNumber='HR002';

update T_Employeeset FSubCompany='Beijing',FDepartment='InfoTech'

where FNumber='IT001';

update T_Employeeset FSubCompany='ShenZhen',FDepartment='InfoTech'

where FNumber='IT002'

update T_Employeeset FSubCompany='Beijing',FDepartment='Sales'

where FNumber='SALES001';

update T_Employeeset FSubCompany='Beijing',FDepartment='Sales'

where FNumber='SALES002';

update T_Employeeset FSubCompany='ShenZhen',FDepartment='Sales'

where FNumber='SALES003';

 

select* from T_Employee

 

------------------------------

------去掉重复数据 ------

------------------------------

--所有员工的部门信息

selectDistinct FDepartmentfrom T_Employee;

 

 

select FDepartment,FSubCompany

from T_Employee

 

--以上两个例子结合起来比较,Distinct针对的是整行进行比较的

selectDistinct FDepartment,FSubCompany

from T_Employee

 

 

 

------------------------------

-----联合结果集Union --------

------------------------------

--创建一个测试表T_TempEmployee,并插入数据

CreateTable T_TempEmployee(FIdCardNumbervarchar(20),FNamevarchar(20),FAgeint,Primarykey(FIdCardNumber));

insertinto T_TempEmployee(FIdCardNumber,FName,FAge)values('1234567890121','Sarani',33);

insertinto T_TempEmployee(FIdCardNumber,FName,FAge)values('1234567890122','Tom',26);

insertinto T_TempEmployee(FIdCardNumber,FName,FAge)values('1234567890123','Yamaha',38);

insertinto T_TempEmployee(FIdCardNumber,FName,FAge)values('1234567890124','Tina',36);

insertinto T_TempEmployee(FIdCardNumber,FName,FAge)values('1234567890125','Konkaya',29);

insertinto T_TempEmployee(FIdCardNumber,FName,FAge)values('1234567890126','Foortia',29);

 

select* from T_TempEmployee

 

--Union关键字,联合2个结果

--2个查询结果结合为1个查询结果

--要求:上下2个查询语句的字段(个数,名字,类型相容)必须一致

select FName,Fagefrom T_TempEmployee

union

select FName,Fagefrom T_Employee

 

 

select FNumber, FName,Fage,FDepartmentfrom T_Employee

union

select FIdCardNumber,FName,Fage,'临时工,无部门'from T_TempEmployee

 

---Union All:不合并重复数据

--Union:合并重复数据

select FName,FAgefrom T_Employee

unionall

select FName,FAgefrom T_TempEmployee

 

select FAgefrom T_Employee

union

select FAgefrom T_TempEmployee

 

--注意:Union因为要进行重复值扫描,所以效率低,因此如果不是确定要合并重复,那么就用Union all

 

--例子:报名

select'正式员工最高年龄',MAX(FAge)from T_Employee

unionall

select'正式员工最低年龄',MIN(FAge)from T_Employee

unionall

select'临时工最高年龄',MAX(FAge)from T_TempEmployee

unionall

select'临时工最低年龄',MIN(FAge)from T_TempEmployee

 

--查询每位正式员工的信息,包括工号,工资,并且在最后一行加上员工工资额合计

select FNumber,FSalaryfrom T_Employee

unionall

select'工资额合计',SUM(FSalary)from T_Employee

 

 

------------------------------

----- SQL其他内置函数 ------

------------------------------

 

--1.数学函数

 

--ABS():求绝对值

--CEILING():舍入到最大整数

--FLOOR():舍入到最小整数

--ROUND():四舍五入

 

selectABS(-3)

 

selectCEILING(3.33)

 

selectCEILING(-3.61)

 

selectFLOOR(2.98)

 

selectFLOOR(-3.61)

 

selectROUND(-3.61,1)--第二个参数是精度,小数点后的位数

 

selectROUND(-3.61,0)

 

selectROUND(3.1415926,3)

 

--2.字符串函数

--LEN():计算字符串长度

--LOWER(),UPPER():转大小写

--LTRIM():去掉字符串左侧的空格

--RTRIM():去掉字符串右侧的空格

--SUBSTRING(string,start_positoin,length):

 

--索引从1开始

 

selectSUBSTRING('abc111',2,3)--结果是bc1

 

select FName,SUBSTRING(FName,2,2)from T_Employee

 

selectLEN('abc') --结果是3

 

select FName,LEN(FName)from T_Employee

 

--没有可以同时既去掉左边空格、又去掉右边空格的TRIM()内置函数,所以先左后右的进行TRim,当然,你也可以先右后左

selectLTRIM(' abc '),RTRIM(' abc '),LEN(LTRIM(RTRIM(' abc ')))

 

 

 

--3.日期函数

--GETDATE():获取当前日期时间

 

--DATEADD(datepart,numbre,date):计算增加以后的日期,

--参数date为待计算的日期;参数number为增量;参数datepart为计量单位,时间间隔单位;

 

--DATEDIFF(datepart,startdate,enddate):计算2个日期之间的差额

 

--DATEPART(datepart,date):返回一个日期的特定部分,比如年月日,时分秒等.

 

/*

写(Sql Server (Access ASP)说明

Year Yy yyyy 1753 ~ 9999

Quarter Qq q 1 ~ 4

Month Mm m 1 ~ 12

Day of year Dy y一年的日数,一年中的第几日 1-366

Day Dd d日, 1-31

Weekday Dw w一周的日数,一周中的第几日 1-7

Week Wk ww周,一年中的第几周 0 ~ 51

Hour Hh h0 ~ 23

Minute Mi n分钟0 ~ 59

Second Ss s 0 ~ 59

Millisecond Ms -毫秒 0 ~ 999

*/

 

selectDATEADD(DAY,3,getdate())

 

selectDATEADD(MONTH,-3,getdate())

 

selectDATEADD(HOUR,8,getdate())

 

selectDATEDIFF(YEAR,'1989-05-01',GETDATE())

 

selectDATEDIFF(HH,GETDATE(),DATEADD(DAY,-3,GETDATE()))

 

--查询员工的工龄,年为单位    

select FName,FInDate,DATEDIFF(year,FInDate,getdate())as 工龄from T_Employee

 

 

--取出每一年入职员工的个数V1

selectDATEDIFF(year,FInDate,getdate()),COUNT(*)

from T_Employee

groupby DATEDIFF(year,FInDate,getdate())

 

--取出每一年入职员工的个数V2

selectDATEPART(YEAR,FInDate),COUNT(*)

from T_Employee

groupby DATEPART(YEAR,FInDate)

 

 

selectDATEPART(YEAR,GETDATE())

 

selectDATEPART(MONTH,GETDATE())

 

selectDATEPART(DAY,GETDATE())

 

selectDATEPART(HH,GETDATE())

 

selectDATEPART(MINUTE,GETDATE())

 

selectDATEPART(SECOND,GETDATE())

 

 

--4.类型转换函数

--CAST(expression as data_type)

--CONVERT(data_type,expression)

 

selectCAST('123'as int),CAST('2010-09-08'as datetime),

CONVERT(datetime,'2010-09-08'),CONVERT(varchar(20),123)

 

--5.空值处理函数isNull

--ISNULL(expression,value)

selectISNULL(FName,'佚名')as 姓名from T_Employee

 

--6.CASE函数用法:

--1.单值判断:相当于switch.case

--CASE expression

--WHEN value1 then returnvalue1

--WHEN value2 then returnvalue2

--WHEN value3 then returnvalue3

--ELSE default_return_value

--END

 

--判断客户类型

 

select FName,

(

case FLevel

when1 then '普通客户'

when2 then '会员'

when3 then 'VIP'

else'未知客户类型'

End

)as 客户类型

from T_Customer

 

--收入水平查询

select FName,

(

case

when FSalary< 2000 then'低收入'

when FSalary>= 2000 and FSalary<=5000then '中等收入'

else'高收入'

end

)as收入水平

from T_Employee

 

--这里有一道关于CASE用法的面试题

--T中有ABC三列,用SQL语句实现:A列大于B列时选择A列,否则选择B列;

--B列大于C列时选择B列,否则选择C列。

select

(

case

when a> b then a else b

end

),

(

case

when b>cthen b else c

end

)

from T

 

 

---------------------------------------

select FNumber,

(

case

when FAmount>0then FAmount

else0

end

)as 收入,

(

case

when FAmount<0then ABS(FAmount)

else0

end

)as 支出

from T

-----------------------------------------

 

--球队比赛那个题

--有一张表T_Scroes,记录比赛成绩:

 

--Date Name Scroe

--2008-8-8拜仁

--2008-8-9奇才

--2008-8-8湖人

--2008-8-10拜仁

--2008-8-8拜仁

--2008-8-12奇才

 

--要求输出下面格式:

--Name

--拜仁 1 2

--湖人 1 0

--奇才 2 0

 

--注意:在中文字符串前加 N,比如 N''

createtable T_Scores(

[Date] datetime nullcollate

[Name] nvarchar(50)

)

CREATETABLE [T_Scores]([Date][datetime]NULL,

[Name][nvarchar](50)COLLATE Chinese_PRC_CI_ASNULL,

[Score][nvarchar](50)COLLATE Chinese_PRC_CI_ASNULL

);

INSERT[T_Scores]([Date],[Name],[Score])VALUES (CAST(0x00009AF200000000AS DateTime), N'拜仁', N'');

INSERT[T_Scores]([Date],[Name],[Score])VALUES (CAST(0x00009AF300000000AS DateTime), N'奇才', N'');

INSERT[T_Scores]([Date],[Name],[Score])VALUES (CAST(0x00009AF300000000AS DateTime), N'湖人', N'');

INSERT[T_Scores]([Date],[Name],[Score])VALUES (CAST(0x00009AF400000000AS DateTime), N'拜仁', N'');

INSERT[T_Scores]([Date],[Name],[Score])VALUES (CAST(0x00009AF200000000AS DateTime), N'拜仁', N'');

INSERT[T_Scores]([Date],[Name],[Score])VALUES (CAST(0x00009AF600000000AS DateTime), N'奇才', N'');

 

select* from T_Scores

 

--列出第一个表格

--统计每支队伍的胜负情况

select Name,

(

case Score

when N''then 1

else0

end

)as ,

(

case Score

when N''then 1

else0

end

)as

from T_Scores

 

 

select Name,

sum

(

case Score

when N''then 1

else0

end

)as ,

sum

(

case Score

when N''then 1

else0

end

)as

from T_Scores

groupby Name

--根据每个队的胜负判断出胜负的场数

 

 

 

 

--5)创建一张表,记录电话呼叫员的工作流水,记录呼叫员编号,对方号码,通话开始时间,通话结束时间,。

--创建一张表T_Callers,记录电话呼叫员的工作流水,记录呼叫员编号、对方号码、通话开始时间、通话结束时间。建表、插数据等最后都自己写SQL语句。

--要求:

-- 1)输出所有数据中通话时间最长的5条记录。

-- 2)输出所有数据中拨打长途号码(对方号码以0开头)的总时长。

-- 3)输出本月通话总时长最多的前三个呼叫员的编号。

-- 4)输出本月拨打电话次数最多的前三个呼叫员的编号。

-- 5)输出所有数据的拨号流水,并且在最后一行添加总呼叫时长。

--记录呼叫员编号、对方号码、通话时长

-- ......

--汇总[市内号码总时长][长途号码总时长]

 

 

--Id CallerNumber TellNumber StartDateTime EndDateTime

--1 001 02088888888 2010-7-10 10:01 2010-7-10 10:05

--2 001 02088888888 2010-7-11 13:41 2010-7-11 13:52

--3 001 89898989 2010-7-11 14:42 2010-7-11 14:49

--4 002 02188368981 2010-7-13 21:04 2010-7-13 21:18

--5 002 76767676 2010-6-29 20:15 2010-6-29 20:30

--6 001 02288878243 2010-7-15 13:40 2010-7-15 13:56

--7 003 67254686 2010-7-13 11:06 2010-7-13 11:19

--8 003 86231445 2010-6-19 19:19 2010-6-19 19:25

--9 001 87422368 2010-6-19 19:25 2010-6-19 19:36

--10 004 40045862245 2010-6-19 19:50 2010-6-19 19:59

 

 

--创建表

createtable T_CallRecords(

idint not null,

CallerNumbervarchar(3),

TellNumbervarchar(13),

StartDateTIme datetime,

EndDateTime datetime,

Primarykey(Id)

);

 

--插入数据

insertinto T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTIme)

values(1,'001','02088888888','2010-7-10 10:01','2010-7-10 10:05');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(2,'002','02088888888','2010-7-11 13:41','2010-7-11 13:52');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(3,'003','89898989','2010-7-11 14:42','2010-7-11 14:49');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(4,'004','02188368981','2010-7-13 21:04','2010-7-13 21:18');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(5,'005','76767676','2010-6-29 20:15','2010-6-29 20:30');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(6,'006','02288878243','2010-7-15 13:40','2010-7-15 13:56');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(7,'007','67254686','2010-7-13 11:06','2010-7-13 11:19');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(8,'008','86231445','2010-6-19 19:19','2010-6-19 19:25');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(9,'009','87422368','2010-6-19 19:25','2010-6-19 19:36');

INSERTINTO T_CallRecords(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)

VALUES(10,'010','40045862245','2010-6-19 19:50','2010-6-19 19:59');

 

--修改呼叫员编号

UPDATE T_CallRecordsSET CallerNumber='001'WHERE Id IN (1,2,3,6,9);

UPDATE T_CallRecordsSET CallerNumber='002'WHERE Id IN (4,5);

UPDATE T_CallRecordsSET CallerNumber='003'WHERE Id IN (7,8);

UPDATE T_CallRecordsSET CallerNumber='004'WHERE Id=10;

 

--数据汇总

select* from T_CallRecords

 

-- 1)输出所有数据中通话时间最长的5条记录。

--@计算通话时间;

--@按通话时间降序排列;

--@取前5条记录。

select top5 CallerNumber,DATEDIFF(SECOND,StartDateTime,EndDateTime)as 总时长

from T_CallRecords

orderby DATEDIFF(SECOND,StartDateTime,EndDateTime)DESC

 

-- 2):输出所有数据中拨打长途号码(对方号码以0开头)的总时长

--@查询拨打长途号码的记录;

--@计算各拨打长途号码的通话时长;

--@对各拨打长途号码的通话时长进行求和。

selectSUM(DATEDIFF(SECOND,StartDateTime,EndDateTime))as 总时长from T_CallRecords

where TellNumberlike '0%'

 

-- 3):输出本月通话总时长最多的前三个呼叫员的编号。

--@按呼叫员编号进行分组;

--@计算各呼叫员通话总时长;

--@按通话总时长进行降序排列;

--@查询前3条记录中呼叫员的编号。

selectdatediff(month,convert(datetime,'2010-06-01'),convert(datetime,'2010-07-22'))--测试

 

select CallerNumber,TellNumber,datediff(month,StartDateTime,EndDateTime)

from T_CallRecords

 

select top3 CallerNumber from T_CallRecords

wheredatediff(month,StartDateTime,getdate())=12--一年前的

groupby CallerNumber

orderby SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime))DESC

 

-- 4)输出本月拨打电话次数最多的前三个呼叫员的编号.

--@按呼叫员编号进行分组;

--@计算个呼叫员拨打电话的次数;

--@按呼叫员拨打电话的次数进行降序排序;

--@查询前3条记录中呼叫员的编号。

select top3 CallerNumber,count(*)

from T_CallRecords

wheredatediff(month,StartDateTime,getdate())=12--一年前的

groupby CallerNumber

orderby count(*)DESC

 

--5)输出所有数据的拨号流水,并且在最后一行添加总呼叫时长:

 

--记录呼叫员编号、对方号码、通话时长

-- ......

--汇总[市内号码总时长][长途号码总时长]

 

--@计算每条记录中通话时长;

--@查询包含不加 0号码,即市内号码的记录;

--@计算市内号码通话总时长;

--@查询包含加 0号码,即长途号码的记录;

--@计算长途号码通话总时长;

--@联合查询。

select'汇总'as 汇总,

convert(varchar(20),

sum((

case

when TellNumbernot like '0%'then datediff(second,StartDateTime,EndDateTime)

else0

end

)))as 市内通话,

sum((

case

when TellNumberlike '0%' thendatediff(second,StartDateTime,EndDateTime)

else0

end

))as 长途通话

from T_CallRecords

unionall

select CallerNumber,TellNumber,datediff(second,StartDateTime,EndDateTime)as 通话时长

from T_CallRecords

 

 

--客户和订单表的练习

--建立一个客户表

createtable T_Customers(

idint not null,

name nvarchar(50)collate chinese_prc_ci_asnull,

ageint null

);

insert T_Customers(id,name,age)values(1,N'tom',10);

insert T_Customers(id,name,age)values(2,N'jerry',15);

insert T_Customers(id,name,age)values(3,N'john',22);

insert T_Customers(id,name,age)values(4,N'lily',18);

insert T_Customers(id,name,age)values(5,N'lucy',18);

 

select* from T_Customers

 

--建立一个销售单表

createtable T_Orders(

idint not null,

billno nvarchar(50)collate chinese_prc_ci_asnull,

customeridint null);

 

insert T_Orders(id,billno,customerid)values(1,N'001',1)

insert T_Orders(id,billno,customerid)values(2,N'002',1)

insert T_Orders(id,billno,customerid)values(3,N'003',3)

insert T_Orders(id,billno,customerid)values(4,N'004',2)

insert T_Orders(id,billno,customerid)values(5,N'005',2)

insert T_Orders(id,billno,customerid)values(6,N'006',5)

insert T_Orders(id,billno,customerid)values(7,N'007',4)

insert T_Orders(id,billno,customerid)values(8,N'008',5)

 

select* from T_Orders

 

select o.billno,c.name,c.age

from T_Ordersas o join T_Customers as c on o.customerid=c.id

--查询订单号,顾客名字,顾客年龄

 

select o.billno,c.name,c.age

from T_Ordersas o join T_Customers as c on o.customerid=c.id

where c.age>15

--显示年龄大于15岁的顾客姓名、年龄和订单号

 

select o.billno,c.name,c.age

from T_Ordersas o join T_Customers as c on o.customerid=c.id

where c.age>(selectavg(age)from T_Customers)

--显示年龄大于平均年龄的顾客姓名、年龄和订单号

 

--子查询练习

--新建一个数据库,名为BookShop

Create database BookShop

 

--创建4张表

createtable T_Reader(FIdINT NOT NULL,FNamevarchar(50),FYearOfBirthINT,FCityvarchar(50),FProvincevarchar(50),FYearOfJoinINT);

createtable T_Book(FIdint not null,FNamevarchar(50),FYearPublishedint,FCategoryIdint);

createtable T_Category(FIdint not null,FNamevarchar(50));

createtable T_ReaderFavorite(FCategoryIdint,FReaderIdint);

 

--分别为4张表插入数据

insertinto T_Category(FId,FName)values(1,'Story');

insertinto T_Category(FId,FName)values(2,'History');

insertinto T_Category(FId,FName)values(3,'Theory');

insertinto T_Category(FId,FName)values(4,'Technology');

insertinto T_Category(FId,FName)values(5,'Art');

insertinto T_Category(FId,FName)values(6,'Philosophy');

 

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(1,'Tom',1979,'TangShan','Hebei',2003);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(2,'Sam',1981,'LangFang','Hebei',2001);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(3,'Jerry',1966,'DongGuan','GuangDong',1995);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(4,'Lily',1972,'JiaXing','ZheJiang',2005);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(5,'Marry',1985,'BeiJing','BeiJing',1999);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(6,'Kelly',1977,'ZhuZhou','HuNan',1995);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(7,'Tim',1982,'YongZhou','HuNan',2001);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(8,'King',1979,'JiNan','ShanDong',1997);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(11,'John',1979,'QingDao','ShanDong',2003);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(9,'Lucy',1978,'LuoYang','HeNan',1996);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,FProvince,FyearOfJoin)values(10,'July',1983,'ZhuMaDian','HeNan',1999);

insertinto T_Reader(FId,FName,FYearOfBirth,FCity,fProvince,FyearOfJoin)values(12,'Fige',1981,'JinCheng','ShanXi',2003);

 

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(1,'About J2EE',2005,4);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(2,'Learning Hibernate',2003,4);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(3,'Tow Cites',1999,1);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(4,'Jane Eyre',2001,1);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(5,'Oliver Twist',2002,1);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(6,'History of China',1982,2);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(7,'History of England',1860,2);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(8,'History of America',1700,2);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(9,'History of The Vorld',2008,2);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(10,'Atom',1930,3);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(11,'RELATIVITY',1945,3);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(12,'Computer',1970,3);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(13,'Astronomy',1971,3);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(14,'How To singing',1771,5);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(15,'DaoDeJing',2001,6);

insertinto T_Book(FId,FName,FYearPublished,FCategoryId)values(16,'Obedience to Au',1995,6);

 

 

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(1,1);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(5,2);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(2,3);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(3,4);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(5,5);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(1,6);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(1,7);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(4,8);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(6,9);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(5,10);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(2,11);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(2,12);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(1,12);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(3,1);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(1,3);

insertinto T_ReaderFavorite(FCategoryId,FReaderId)values(4,4);

 

select* from T_Book

 

select* from T_Category

 

select* from T_Reader

 

select* from T_ReaderFavorite

 

--并列查询

select1 as f1,2,(selectMIN(FYearPublished)from T_Book),

(selectMAX(FYearPublished)from T_Book)as f4

 

--查询入会日期在2001或者2003年的读者信息

select* from T_Reader

where FYearOfJoinin (2001,2003)

 

--between...and不同

select* from T_Reader

where FYearOfJoinbetween 2001 and2003

 

--查询有书出版的年份入会的读者信息

select* from T_Reader

where FYearOfJoinin

(

select FYearPublishedfrom T_Book

)

 

--SQL Server 2005之后的版本内置函数:ROW_NUMBER(),称为开窗函数,可以进行分页等操作。

selectROW_NUMBER() over(orderby FSalary DESC) as Row_Num,

FNumber,FName,FSalary,FAgefrom T_Employee

--特别注意,开窗函数row_number()只能用于selectorder by 子句中,不能用于where子句中

 

--查询第3行到第5行的数据

select* from

(

selectROW_NUMBER() over(orderby FSalary DESC) as Row_Num,

FNumber,FName,FSalary,FAgefrom T_Employee

)as e1

where e1.Row_Num>=3and e1.Row_Num<=5

 

 

四、SQL其他概念

--索引

1什么是索引?优缺点是什么?

索引是对数据库表中一列或多列的值进行排序的一种单独的、物理的数据库结构。

优点:

 1)大大加快数据的检索速度;

 2)创建唯一性索引,保证数据库表中每一行数据的唯一性;

 3)加速表和表之间的连接;

 4)在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。

缺点:

 1)索引需要占物理空间;

 2)当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。

--创建索引,在列上点击右键,写一个名称,选定列即可。

2业务主键和逻辑主键

业务主键是使用有业务意义的字段做主键,比如身份证号,银行账号等;

逻辑主键是使用没有任何业务意义的字段做主键。因为很难保证业务主键不会重复(身份证号重复)、不会变化(账号升位),因此推荐使用逻辑主键。

 

3SQL Server 两种常用的主键数据类型

1)int( bigint)+ 标识列(又称自动增长字段)

用标识列实现字段自增可以避免并发等问题,不要开发人员控制自增。用标识列的字段在Insert的时候不用指定主键的值。

优点:占用空间小、无需开发人员干预、易读;

缺点:效率低,数据导入导出的时候很痛苦。

设置:"修改表"->选定主键->"列属性"->"标识规范"选择""

2) uniqueidentifier(又称GUIDUUID)

GUID算法是一种可以产生唯一表示的高效算法,它使用网卡MAC、地址、纳秒级时间、芯片ID码等算出来的,这样保证每次生成的GUID永远不会重复,无论是同一计算机还是不同计算机。在公元3400年前产生的GUID与任何其他产生过的GUID都不相同。

SQL Server中生成GUID的函数newid()

优点:效率高、数据导入导出方便;

缺点:占用空间大、不易读。

业界主流倾向于使用GUID