SQL Server 数据库 T-SQL 高级查询

一、在查询中使用函数

先创建一个工资表

create table 工资表
(
编号 int identity (1,1) not null,
姓名 nvarchar(10) not null,
身份证号 varchar(18) primary key,
职务 nvarchar(30) not null,
出生日期 datetime not null,
基本工资 money not null,
备注 nvarchar(1000),
)

在这里插入图片描述
往表里写入数据

insert into [工资表](姓名,身份证号,职务,出生日期,基本工资)
values ('张三','10086','DBA','1995/3/3','10000')
insert into [工资表](姓名,身份证号,职务,出生日期,基本工资)
values ('李四','20086','运维工程师','1992/2/2','9000')
insert into [工资表](姓名,身份证号,职务,出生日期,基本工资,备注)
values ('王五','22286','运维经理','1990/5/5','15000','技术全面')
insert into [工资表](姓名,身份证号,职务,出生日期,基本工资)
values ('孙七','33386','运维工程师','1995/1/1','8000')
insert into [工资表](姓名,身份证号,职务,出生日期,基本工资)
values ('赵六','66086','运维总监','1980/7/7','36000')
insert into [工资表](姓名,身份证号,职务,出生日期,基本工资)
values ('张嘴','66686','DBA','1989/6/6','9000')
insert into [工资表](姓名,身份证号,职务,出生日期,基本工资,备注)
values ('王者','88086','CTO','1975/11/11','55000','项目经验丰富')

查询 工资表 中所有员工信息:

select * from [工资表] 

在这里插入图片描述

1.系统函数

系统函数用来获取有关 SQL Server 中对象和设置的系统信息。

函数名 描述
CONVERT() 数据类型转换
CAST() 数据类型转换,与 CONVERT 相比语法比较简单,转换功能较少
CURRENT_USER() 返回当前登录的数据库用户名
DATALENGTH() 返回用于指定表达式的字节数
HOST_NAME() 返回当前用户所登录的计算机的名称
SYSTEM_USER() 返回当前登录系统用户名
USER_NAME() 从给定的用户 ID 中返回数据库用户名
  • 上面所有这些函数,可以在 T-SQL 中混合使用,得到符合特殊要求的查询输出。

2.字符串函数

字符串函数用于控制返回给用户的字符串,这些功能仅用于字符型数据。

函数名 描述
CHARINDEX() 用来寻找一个指定的字符串在另一个字符串中的起始位置
LEN() 返回传递给它的字符串长度
UPPER() 把转递给它的字符串转换为大写
LTRIM() 清除字符左边的空格
RTRIM() 清除字符右边的空格
RIGHT() 替换一个字符串中的字符
STUFF() 在一个字符串中,删除指定位置指定长度的字符串,并在该位置插入一个新的1字符串
  • 字符串在信息处理时由特殊的地位,几乎所有信息都需要转换成字符串才能正确显示,尤其是不同数据拼接起来显示的使用更加广泛。
  • 字符串拼接很简单,两个字符串之间使用"+"即可。

将 工资表 中所有运维工程师的姓名和基本工资组合:

select '运维工程师 '+姓名+' 的基本工资是:'+CAST(基本工资 as varchar(10))+'元'
from [工资表]
where 职务='运维工程师'

在这里插入图片描述

3.日期函数

在 SQL Server 中不能直接对日期运用数学函数,需要使用日期函数操作日期值。日期函数帮助提取日期值中的日、月及年,以便分别操作它们。

函数名 描述
GETDATE() 取得当前的系统日期
DATEADD() 添加指定的年(YY)、月(MM)、或日(DD)
DATEDIFF() 比较两个日期之间的指定日期部分的差
DATENAME() 显示指定日期中特定部分的字符串
DATEPART() 显示日期中指定日期部分的整数形式
  • 日期函数是实际生活中使用频率非常高的一类函数,可以说很多应用都与日期函数关联。

显示距离当前 10 天之后的日期和时间:

select DATEADD (DD,10,GETDATE())

在这里插入图片描述
显示 工资表 中所有人的姓名和年龄:

select 姓名,DATEDIFF(YY,出生日期,GETDATE()) AS 年龄 from [工资表] 

在这里插入图片描述
显示 工资表 中所有 90 后员工的姓名和出生年份:

select 姓名,DATENAME(YEAR,出生日期) AS 出生年份 
from [工资表] 
where 出生日期 BETWEEN '1990-01-01' AND '1999-12-31'

在这里插入图片描述

4.聚合函数与分组查询

在查询时还会经常碰到的是取某些列的最大值、最小值、平均值等信息,有时候还需要计算出究竟查询到多少行数据项。这个时候就可以使用聚合函数,因为聚合函数能够基于列进行计算,并返回单个值。

1)聚合函数

常用的聚合函数有SUM()、AVG()、MAX()、MIN()、COUNT()。

  • SUM():SUM() 函数返回表达式中所有数值的总和,它只能用于数字类型的列,不能够汇总字符串、日期等其他数据类型。
  • AVG():AVG() 函数返回表达式中所有数值的平均值,它也只能用于数字类型的列。
  • MAX():MAX() 函数返回表达式中的最大值,它能够用于数字型、字符型及日期/时间类型的列。
  • MIN():MIN() 函数返回表达式中的最小值,它能够用于数字型、字符型及日期/时间类型的列。
  • COUNT():COUNT() 函数返回表达式中非空值的计数,它可以用于数字和字符类型的列。另外,也可以使用星号 (*) 作为 COUNT() 函数的表达式,使用星号可以不必指定特定的列而计算所有的行数。

查询 工资表 中所有员工基本工资的总和:

select SUM(基本工资) AS 总工资 from [工资表] 

在这里插入图片描述
查询 工资表 中所有员工的平均基本工资:

select AVG(基本工资) AS 平均工资 from [工资表] 

在这里插入图片描述
查询 工资表 中最高和最低的基本工资:

select MAX(基本工资) AS 最高工资,MIN(基本工资) AS 最低工资 from [工资表] 

在这里插入图片描述
查询 工资表 中全部行数:

select COUNT(*) AS 总行数 from [工资表] 

在这里插入图片描述
查询 工资表 中 90 后员工的人数:

select COUNT(出生日期) AS '90后人数'
from [工资表] 
where 出生日期>='1990-01-01'

在这里插入图片描述

2)分组查询

分组查询就是将表中的数据通过 GROUP BY 子句分类组合,再根据需要得到统计信息。如果需要对分组结果进行筛选,只显示满足条件的组,需要使用 HAVING 子句。

查询 工资表 中每个职务的平均工资:

select 职务,AVG(基本工资) AS 职务平均工资 from [工资表] GROUP BY 职务 

在使用 GROUP BY 关键字时,在 SELECT 列表中可以指定的项目有限的,SELECT 语句中仅允许以下几项:

  • 被分组的列。
  • 为每个分组返回一个值的表达式,如果一个列名作为参数的聚合函数。

在这里插入图片描述
查询 工资表 中平均工资小于 10000 的职务:

select 职务,AVG(基本工资) AS 职务平均工资 from [工资表] GROUP BY 职务
HAVING AVG(基本工资)<10000

当 GROUP BY 子句使用 HAVING 子句时,查询结果只返回满足 HAVING 条件的组。HAVING 子句与 WHERE 子句类似,均用于设置限制条件。但 HAVING 子句和 WHERE 子句的作用有如下区别:

  • WHERE 子句的作用是在对查询结果进行分组前,根据 WHERE 条件筛选数据,条件中不能包含聚合函数。
  • HAVING 子句的作用是在分组之后筛选满足条件的组,条件中经常包含聚合函数,也可以使用多个分组标准进行分组。

当 WHERE 和 HAVING 同在一个 SELECT 语句中使用时,执行顺序为 WHERE——》GROUP BY——》HAVING。
在这里插入图片描述
查询 工资表 中平均工资小于 10000 的职务,前提是员工 张三 不计算在内:

select 职务,AVG(基本工资) AS 职务总工资 from [工资表] 
where 姓名 != '张三'
GROUP BY 职务
HAVING AVG(基本工资)<10000

在这里插入图片描述

3)数学函数

数学函数用于对数值进行代数运算。

函数名 描述
ABS() 取数值表达式的绝对值
CEILING() 取大小或等于指定数值、表达式的最小整数
FLOOR() 取小数或等于指定表达式的最大整数
[POWER() 取数值表达式的幂值
ROUND() 将数值表达式四舍五入为指定精度
SIGN() 对于正数返回+1,对于负数返回-1,对于0则返回0
SQRT() 取浮点表达式的平方根

查询 工资表 中所有人平均工资,用CEILING()取整:

select CEILING(AVG(基本工资)) AS 平均工资 from [工资表] 

在这里插入图片描述

4)函数综合应用

在实际生产环境中可以根据需要,将函数进行不同的组合,以满足实际需求。

查询未满 30 岁的员工的生日和年龄,并计算出距离 30 岁的天数,最后用字符串拼接显示结果:

1. 查询正确数据结果

  • 计算年龄使用日期函数 DATEDIFF(),比较"出生日期"和"当前日期",其中使用参数"YY"取其 Year 的差。
  • 计算距离 30 岁的天数也使用日期函数 DATEDIFF(),比较"当期日期"和"出生日期+30年",其中使用 DATEADD()实现将出生日期加 30 年,使用参数 “DD” 比较 Day 的差。
select 姓名,出生日期,DATEDIFF(YY,出生日期,GETDATE()) AS 年龄,DATEDIFF(DD,GETDATE(),DATEADD(YY,30,出生日期)) AS 距离30岁天数
from [工资表] 
where DATEDIFF(YY,出生日期,GETDATE())<=30 and 姓名!='王五'
ORDER BY 出生日期 

在这里插入图片描述
2. 将结果用字符串拼接

  • 使用系统函数 CONVERT(varchar(10),出生日期,111)将 DATETIME 类型转换为字符型,定义长度 10 的目的是不显示 10 个字符串以后的内容,“111” 是参数 style 的类型值,参数 style 代表日期格式,有很多种,“111” 代表的 style 格式是 “YYYY/MM/DD” 。
  • 使用系统函数 CAST()将年龄和天数转化为字符串。
select
'员工 '+姓名+
' 的生日是'+CONVERT(varchar(10),出生日期,111)+
',现在年龄是 '+CAST(DATEDIFF(YY,出生日期,GETDATE()) AS varchar(10))+'岁'+
',距离30岁生日还有 '+
CAST(DATEDIFF(DD,GETDATE(),DATEADD(YY,30,出生日期)) AS varchar(10))+'天'
from [工资表]
where DATEDIFF(YY,出生日期,GETDATE())<=30 and 姓名!='王五'
ORDER BY 出生日期

在这里插入图片描述

二、使用 T-SQL 实现多表查询

如果一个查询需要对多个表进行操作,就称为联接查询,联接查询的结果集或结果称为表之间的联接。联接查询实际上是通过各个表之间共同列的关联性来查询数据的,它是关系数据库查询最主要的特征。

先创建两个表:

create table A
(
姓名 nvarchar(10) not null,
学校 nvarchar(20) not null,
)
create table B
(
姓名 nvarchar(10) not null,
职业 nvarchar(20) not null,
)

在这里插入图片描述
往 A 表中写入数据:

insert into A (姓名,学校) values ('张三','清华大学')
insert into A (姓名,学校) values ('李四','北京大学')
insert into A (姓名,学校) values ('王五','武汉大学')
insert into A (姓名,学校) values ('孙七','985大学')
insert into A (姓名,学校) values ('老八','211大学')

往 B 表 写入 数据:

insert into B (姓名,职业) values ('张三','咨询师') 
insert into B (姓名,职业) values ('李四','律师') 
insert into B (姓名,职业) values ('老八','作家') 
insert into B (姓名,职业) values ('小明','明星') 
insert into B (姓名,职业) values ('小黑','保安') 

查询 A 表 和 B 表:
在这里插入图片描述

1.表联接类型

表联接类型可以分为内联接、外联接和交叉联接等。

1)内联接

内联接(inner join)是最常用的一种联接方式,只返回两个数据集合之间匹配关系的行,将位于两个互相交叉的数据集合中重叠部分以内的数据行联接起来。内联接使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中联接相匹配的数据行。

在表 A 和表 B 种使用内联接查询学生姓名、学校和职业:

  • 实现方式一:在 where 子句中指定联接条件。
select A.姓名 姓名A,A.学校 学校A,B.姓名 姓名B,B.职业 职业B
from A,B
where A.姓名=B.姓名

在这里插入图片描述

  • 实现方式二:在 from 子句中使用 INNER JOIN ON子句来实现。
select A.姓名 姓名A,A.学校 学校A,B.姓名 姓名B,B.职业 职业B
from A INNER JOIN B ON A.姓名=B.姓名

在这里插入图片描述

2)外链接

外联接(outer join)是对内联接的扩充,除了将两个数据集合中重复部分以内的数据行联接起来之外,还可以根据要求返回左侧或右侧表中非匹配的数据或全部的数据。

外联接分为以下几种:

  • 左外联接(left join 或 left outer join):左外联接的结果集包括做左表的所有行。如果左表的某一行在右表中没有匹配行,则右侧返回空值,否则返回相应值。
  • 右外联接(right join 或 full outer join):右外联接是左外联接的反向联接,将返回右表的所有行。如果右表的某一行在左表中没有匹配行,则左表返回空值,否则返回相应值。
  • 全联接/完整外联接(full join 或 full outer join):将返回左表和右表中所有行。将某一行在另一个表中没有匹配行时,另一个表返回空值,否则返回相应值。

1.左外联接
在表 A 和表 B 中使用左外联接查询学生姓名、学校和职业:

select A.姓名 姓名A,A.学校 学校A,B.姓名 姓名B,B.职业 职业B
from A LEFT JOIN B ON A.姓名=B.姓名

在这里插入图片描述
2.右外联接
在 表 A 和表 B 中使用右外联接查询学生姓名、学校和职业:

select A.姓名 姓名A,A.学校 学校A,B.姓名 姓名B,B.职业 职业B
from A RIGHT JOIN B ON A.姓名=B.姓名

在这里插入图片描述
3.完整外联接
在 表 A 和表 B 中使用完整外联接查询学生姓名、学校和职业:

select A.姓名 姓名A,A.学校 学校A,B.姓名 姓名B,B.职业 职业B
from A FULL JOIN B ON A.姓名=B.姓名

在这里插入图片描述
总结:

  • 在外联接中参入联接的表有主从之分,以主表的每行数据去匹配从表的数据列,符合联接条件的数据将直接返回结果集中;
  • 对于那些不符合联接条件的列,将被填上 NULL 值后再返回结果集中。

3)交叉链接

交叉联接就是表之间没有任何关联条件,查询将返回左表与右表挨个联接的所有行,就是左表中的每行与右表中的所有行再一一组合,相当于两个表"相乘"。

猜你喜欢

转载自blog.csdn.net/weixin_46902396/article/details/110876752