1.查询数据
select [distinct] <目标列表达式>[,...n]
from <表或视图名> [,...n]
[where <条件表达式>]
[group by <列名1> [having <条件表达式> ] ]
[order by <列名2> [asc | desc] ]
1.1简单查询
简单查询指的是仅涉及一张表的查询,例如,查询一张表中的某些列,查询一张表中满足给定条件的元组,等等。
select [distinct] <目标列表达式>[,...n] form <表或视图名>
(1) 询所有列
select * from Employee
(2) 查询指定列
select Companyname,Contactname,Address from Customer
(3) 使用distinct关键字消除重复元组
select distinct DepartmentID from Employee
注:1.distinct关键字的作用范围是整个查询列表,而不是单独的某个列,因此紧跟在select之后书写。
(4) 为列起别名
select Employeename as 员工姓名,性别=Sex from Employee
注:1.当列的别名含有空格时需要用单引号括起。
(5) 查询计算列(属性列,常量,变量和函数构成)
select Employeename,Salary,Salary*1.1 as 提高后的工资 from Employee
1.2查询满足条件的元组
查询满足条件的元组是通过在where语句子句中查询条件来实现的。在SQL语句中,查询条件是一个返回TRUE(真),FALSE(假),UNKNOWN(未知)三种逻辑值的逻辑表达式。
(1)比较大小
比较大小就是用比较运算符连接两个同类操作数(op1和op2)来表达查询条件
== | 等于 | <= | 小于等于 |
---|---|---|---|
> | 大于 | !=或<> | 不等于 |
< | 小于 | !> | 不大于 |
>= | 大于等于 | !< | 不小于 |
查询工资大于3000的员工姓名和工资
select Employeename,Salary from Employee where Salary >3000
查询工资在3400以下的女性员工的姓名和工资
select Employeename,Sex,Salary from Employee where Salary <3400 and Sex='女'
(2) 确定范围
确定范围就是用三目运算符【NOT】 BETWEEN AND 连接三类操作数,来表达查询条件
op1 [not] between op2 and op3
注:op1,op2,op3是由常量,变量,函数构成的算术表达式或字符串表达式
查询工资在5000到7000的员工信息
select * from Employee where Salary between 5000 and 7000
(3) 确定集合
确定集合就是用运算符【NOT】 IN连接两个操作数(op1和op2)来表达查询条件,一般格式:
op1 [not] in op2
注:op1是由常量,变量,函数构成的算术表达式或字符串表达式,op2是一个集合,在SQL语言中常表示为(e1,e2,e3,...,en)的形式
在销售订单表中sell_order,查询员工编号为1,5,7员工接收订单的信息
select * from Sell_order where Employeeid in (1,5,7)
在销售订单表中sell_order,查询员工编号不是1,5,7员工接收订单的信息
select * from Sell_order where Employeeid not in (1,5,7)
查询既不来自杭州,也不来自宁波的学生的信息
select * from 学生表 where 籍贯 not in ('杭州','宁波')
查询学号后两位是‘09’的学生的信息
select * from 学生表 where substring(学号,6,2) in ('09')
(4) 字符串匹配
1、 模糊匹配
-
Like 通常与通配符一起使用
% 表示0~n个任意字符
_ 表示单个任意字符
[ ] 表示方括号里列出的任意一个字符
[^] 表示不在方括号里列出的任意一个字符
Like ‘AB%’ 以AB开始的任意字符串
Like ‘%AB’ 以AB结束的任意字符串
Like ‘%AB%’ 包含AB的任意字符串
Like ‘ _AB’ 以AB结束的3个字符的字符串
Like ‘[ACB]%’以A、C或B开始的任意字符串
Like ‘[A-T]ing’ 以ing结束,总共4个字符,首字符为A到T
Like ‘M[^A]%’ 以M开始,第二字符不是A的任意长度的字符串
(1)找出所有姓章的员工信息
select * from Employee where EmployeeName like '章%'
(2)找出所有姓李的和姓章的员工
select * from Employee where EmployeeName like '[章李]%'
(3)找出所有姓李的,名为一个汉字的员工
select * from Employee where EmployeeName like '李_'
(4)找出所有不姓李的
select * from Employee where EmployeeName like '[^李]%'
(5)查询课程名以“DB_”开头的课程信息
select * from 课程表 where 课名 like 'DB\_%' escape '\'
(5) 空值查询
涉及空值的查询就是运用运算符 IS [NOT] NULL 对一个表达式exp的值进行判断,判断它是否为NULL,一般格式:
exp is [not] null
(1)找出目前有哪些主管位置不为空
select Departmentid,Departmentname from Department where Manager is not null
(6) 多重条件查询
多重查询就是用逻辑运算符NOT,AND,OR和括号将多个逻辑表达式连接起来,形成一个更复杂的逻辑表达式。括号优先级最高,NOT其次,AND再次之,OR的优先级最低。
(1) 查询这样的男生,电话号码的前三位是130,他来自杭州或者宁波,他既不主修电子商务专业,也不主修信息管理专业
select * from 学生表 where 性别='男' and substring(移动电话,1,3)='130' and (籍贯 ='宁波'or 籍贯 ='杭州') and 专业 not in ('电子商务','信息管理')
1.3 对查询结果排序
如果没有指定查询结果的显示顺序,DBMS将按其最方便的顺序。用户也可用ORDER BY子句指定按照一个或者多个属性列的升序ASC或者降序DESC重新排列结果,ASC为默认值
(1)按工资降序显示员工的姓名和工资,如果工资相同则按姓名的升序排列
select EmployeeName,Salary from Employee order by Salary,EmployeeName asc
注:order by子句中的先后顺序决定了排序过程中的优先级,例题中order by Salary,EmployeeName asc表示结果集先按工资升序(默认)排列,工资相同时按照名字升序排列。
可以在order by子句中可以采用三种方式来表示这个计算列
1. 这个计算列的表达式
2. 这个计算列的顺序编号(select子句中的顺序编号,从1开始)
3. 这个计算列的别名
1.4 常用的统计函数
函数格式 | 函数功能 |
---|---|
COUNT([DISTINCT]*) | 统计元组个数 |
COUNT([DISTINCT]<列表达式>) | 统计列值个数 |
SUM([DISTINCT]<列表达式>) | 计算数值型列表达式的总和 |
AVG([DISTINCT]<列表达式>) | 计算数值型列表达式的平均值 |
MAX([DISTINCT]<列表达式>) | 列表达式的最大值 |
MIN([DISTINCT]<列表达式>) | 列表达式的最小值 |
(1)统计一下公司中有多少员工
select count(distinct EmployeeName) as 公司员工总数 from Employee
(2)查询最高与最低工资
select min(Salary) as 最低工资,max(Salary) as 最高工资 from Employee
注:统计列为空值不参与统计计算,如果结合where子句用统计函数,则只有满足where条件的才参与统计
1.5 分组查询
GROUP BY子句可以将查询的结果集按一列或者多列取值相等的原则进行分组。含有GROUP BY子句的查询称为分组查询: GROUP BY <分组列>[,...n]
(1) 查询男女员工的平均工资
select Sex,Avg(Salary)as 平均工资 from Employee group by Sex
(2) 各部门的最高工资
select DepartmentID,Max(Salary)as 最高工资 from Employee group by DepartmentID
(3) 在销售表sell_order表中,统计目前各种商品的订单总数
select Productid as 商品编号,sum(Sellordernumber) as 商品总数 from Sell_Order group by Productid
注:GROUP BY子句的别名只能是FROM子句所列表的列名,不能是列的别名
使用GROUP BY子句后,SELECT子句的目标列表达式所涉及的列必须满足:要么在GROUP BY子句中,要么在某个统计函数中
1.6 Having短语分组
如果分组后还要求按一定条件对这些组进行筛选,最终只能输出满足指定条件的组,则可以使用HAVING短语指定筛选条件,指定组或聚合的搜索条件,通常在group by子句中使用
注:WHERE条件不能直接包含统计函数,而HAVING条件所涉及的列必须要么在GROUP BY子句中,要么在某个统计函数中。
(1)在销售表sell_order中,查询目前订单总数超过1000的商品订单信息
select Productid as 商品编号,sum(Sellordernumber) as 商品总数 from Sell_Order group by Productid having sum(Sellordernumber)>1000
(2)在销售表sell_order中,查询订购两种以上商品的客户编号
select Customerid as 客户编号 from Sell_Order group by Customerid having count(*)>2
1.7 连接查询
单表查询的FROM子句只涉及一张表,而连接查询的FROM子句涉及多张表
JOIN和ON关键字将连接条件和普通查询条件分开。普通查询条件仍写在WHERE子句中。JOIN用于连接两张表,ON则用于给出这两张表的连接条件。
select 子句 from <表名> {join <表名> on <连接条件>}[...n] [where <普通查询条件>] [其他子句]
注:1. 由于不同表的某些列可能会重名,故如果查询的某些子句涉及这些重名列,则需要在列名前边加”<表名>.“作为限定。
2. 在连接查询中如果没有WHERE子句,查询结果将是没有意义的笛卡尔积,为了避免这种情况,WHERE条件应包括必须的连接条件和普通查询条件
3. 在涉及n张表的连接查询中,至少应该包括n-1个连接条件,否则这n张表之间的某些位置将蜕化成没有意义的笛卡尔积。
(1)查询已订购了商品客户的公司名称,联系人姓名和所订商品编号和订购数量。
select Companyname,Contactname,productid,sellordernumber from Customer C join Sell_Order S on C.CustomerID=S.CustomerID
(2)查询“三川实业有限公司”的订单信息。
select C.CompanyName,productid,sellordernumber,employeeid,C.CustomerID,sellorderdate from Customer C join Sell_Order S on S.CustomerID=C.CustomerID where Companyname='三川实业有限公司'
(3)查询“三川实业有限公司”订购的商品信息,包括商品的名称、价格和数量。
select P.ProductID,P.ProductName,P.Price,S.SellOrderNumber from Customer C join Sell_Order S on S.CustomerID=C.CustomerID join Product P on S.ProductID=P.ProductID where Companyname='三川实业有限公司'
1.8 外连接
分类:左外连接、右外连接和全外连接。
左向外连接(left outer join):只包括左表的所有行,不包括右表的不匹配行的外连接;
右向外连接(right outer join):只包括右表的所有行,不包括左表的不匹配行的外连接。
全外部连接(full outer join):既包括左表不匹配的行,也包括右表的不匹配的行的连接
1.左外连接
(4)查询是否所有的员工均接受了销售订单,包括员工的姓名和订单信息
select EmployeeName,SellOrderID,ProductID,SellOrderNumber,CustomerID,SellOrderDate from Employee left outer join Sell_Order on Employee.EmployeeID = Sell_Order.EmployeeID
2.右外连接
(5)查询所有的供应商提供的商品情况。
select PV.ProviderName,ProductID from Purchase_order PO right outer join Provider PV on PO.ProviderID=PV.ProviderID
3.全外连接
(6)使用全外连接查询客户和商品的订购信息,包括客户名称、联系人姓名、订购的商品名称、订购的数量和订购日期。
select C.CompanyName ,C.ContactName,S.ProductID,S.SellOrderNumber,S.SellOrderDate from Customer C full outer join Sell_Order S on C.CustomerID=S.CustomerID
1.9 子查询
1. 嵌套查询
- 检查给定值是否在结果集中
检查给定值是否在结果集中是指父查询与子查询之间用IN进行连接,判断父查询的某个属性列的值是否在子查询的结果中。
(1)查询选修了课程名为“数据库原理”的学生学号和姓名
select 学号,姓名 from 学生表 where 学号 in (select 学号 from 选课表 where 开课号 in (select 开课号 from 开课表 where 课号 in (select 课号 from 课程表 where 课名=‘数据库原理')))
(2) 查询已经接收销售订单的员工姓名和工资信息。
select E.EmployeeName,E.Salary from Employee E where EmployeeID in(select EmployeeID from Sell_Order)
(3) 查询没有接收销售订单的员工姓名和工资信息。
select E.EmployeeName,E.Salary from Employee E where EmployeeID not in(select EmployeeID from Sell_Order)
(4) 查询订购牛奶的客户的名称和联系地址。
select C.CompanyName,C.Address from Customer C where CustomerID in(select CustomerID from Sell_Order where ProductID in(select ProductID from Product where ProductName='牛奶'))
注:1. 嵌套查询的求解顺序是由内向外进行的,子查询的结果建立父查询的查询条件。
2. 没有嵌套层数限制。
3. 用IN或比较运算符进行连接,则子查询的SELECT子句只能有一个列表达式。
4.列表达式的左边和右边select子句中的列表达式应当具有相同含义,否则无正确结果。
- 用给定值和结果集中的元素进行大小比较
单值比较
(1)查找员工“吴昊”所在的部门名称。
select E.EmployeeName,E.DepartmentID from Employee as E where E.EmployeeName='吴昊'
(2)查找年龄最小的员工姓名、性别和工资。
select E.EmployeeName,E.Sex,E.Salary from Employee as E where E.BirthDate >=all(select BirthDate from Employee)
(3)查找比平均工资高的员工的姓名和工资。
select E.EmployeeName,E.Salary from Employee as E where E.Salary > (select Avg(Salary) from Employee)
多值比较
(4)查找年龄比销售部的员工小的员工(多值)
select E.EmployeeName from Employee as E where E.BirthDate > all(select BirthDate from Employee where DepartmentID =(select DepartmentID from Department where DepartmentName='销售部') )
< | > | ||
---|---|---|---|
ANY | IN | <MAX | >MIN |
ALL | - | <MIN | >MAX |
- 检查结果为空
可以用关键字EXISTS来检查子查询的结果集是否为空,检查结果是逻辑值“真”或“假”。如果EXISTS检查返回真,则子查询结果集不空,否则子查询结果集为空
(1)查询选修了开课号为010101的课程的学生姓名
select 姓名 from 学生表 as S where exists(select * from 选课表 as E where E.学号=S.学号 and 开课号='010101')
(2)利用相关子查询,查询已经接收销售订单的员工姓名和工资信息。
select E.EmployeeName,E.Salary from Employee as E where exists( select * from Sell_Order as S where S.EmployeeID=E.EmployeeID)
注:1. 子查询的条件往往要引用上层查询涉及的表,但是父查询不允许引用子查询涉及的表
2.子查询的select子句一般写成select * 即可,无需给出具体列名
2.0 联合查询
使用union将多个查询结果合并起来
查询计算机专业和信息管理专业的学生信息
select * from 学生表 where 专业='计算机' union select * from 学生表 where 专业='信息管理'
注:系统会自动去除重复元组,但是参加UNION操作的各结果表的列数必须相同,对应列数的数据结构也必须相同。