目录
20200329
问题1
给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求只使用一个更新(Update)语句,并且没有中间的临时表。
注意,您必只能写一个 Update 语句,请不要编写任何 Select 语句。
答案
update salary set sex = IF(sex = 'm', 'f', 'm')
知识点
可以使用 if 函数判断 列的值 进行数据交换 当没有where 条件的时候会更新全表
IF 函数用法
IF(expr,v1,v2) 如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2
问题2
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary)。
答案
方法1:将 Salary 去重后降序排列,再返回第二条记录可得第二大的值
也许只有一个 Salary 值,将返回 null
select (select distinct Salary from Employee limit 1,1) as secondhighestsalary;
方法2:找出小于该字段最大值的最大值,即为第二大值
select MAX(Salary) as secondhighestsalary from Employee
where Salary <(select MAX(Salary) from Employee );
知识点
limit N # 返回 N 条记录
offset M # 跳过 M 条记录,M 默认为 0
limit M,N # 相当于 limit N offset M,从第 M 条记录开始,返回 N 条记录
20200412
问题3
查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t
CREATE TABLE salaries
(
emp_no
int(11) NOT NULL,
salary
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,from_date
));
答案:
select emp_no, count(emp_no)as t from salaries
group by emp_no having t>15;
知识点:
此题应注意以下四点:
1、用COUNT()函数和GROUP BY语句可以统计同一emp_no值的记录条数
2、根据题意,输出的涨幅次数为t,故用AS语句将COUNT(emp_no)的值转换为t
3、由于COUNT()函数不可用于WHERE语句中,故使用HAVING语句来限定t>15的条件 4、最后存在一个理解误区,涨幅超过15次,salaries中相应的记录数应该超过16(从第2条记录开始算作第1次涨幅),不过题目为了简单起见,将第1条记录当作第1次涨幅,所以令t>15即可
注意: 严格来说,下一条salary高于本条才算涨幅,但本题只要出现了一条记录就算一次涨幅,salary相同可以理解为涨幅为0,salary变少理解为涨幅为负
疑惑:
此题应该是默认每次变化都是增长且不重复的。
问题4
找出所有员工当前(to_date=‘9999-01-01’)具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示
CREATE TABLE salaries
(
emp_no
int(11) NOT NULL,
salary
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,from_date
));
答案:
方法1:适用小表
select distinct salary from salaries
where to_date='9999-01-01' order by salary desc
方法2:适用大表
select salary from salaries
where to_date='9999-01-01' group by salary
order by salary desc
知识点
1.大表一般用distinct效率不高,大数据量的时候都禁止用distinct,建议用group by解决重复问题
2.WHERE语句在GROUP BY语句之前,SQL会在分组之前计算WHERE语句。
HAVING语句在GROUP BY语句之后,SQL会在分组之后计算HAVING语句
having 是过滤组 where过滤行
不足:
需增强order by 语句
问题5
获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date=‘9999-01-01’
CREATE TABLE dept_manager
(
dept_no
char(4) NOT NULL,
emp_no
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,dept_no
));
CREATE TABLE salaries
(
emp_no
int(11) NOT NULL,
salary
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,from_date
));
答案
select d.dept_no,d.emp_no,s.salary
from salaries as s inner join dept_manager as d
on s.emp_no = d.emp_no
and s.to_date='9999-01-01'
and d.to_date='9999-01-01'
错误解法
select dept_no,emp_no,salary from dept_manager
where to_date='9999-01-01'
from salaries inner join dept_manager
on salaries.emp_no = dept_manager.emp_no
解析:
先联结再where
问题6
获取所有非manager的员工emp_no
CREATE TABLE dept_manager
(
dept_no
char(4) NOT NULL,
emp_no
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,dept_no
));
CREATE TABLE employees
(
emp_no
int(11) NOT NULL,
birth_date
date NOT NULL,
first_name
varchar(14) NOT NULL,
last_name
varchar(16) NOT NULL,
gender
char(1) NOT NULL,
hire_date
date NOT NULL,
PRIMARY KEY (emp_no
));
答案:
方法一:先使用LEFT JOIN连接两张表,再从此表中选出dept_no值为NULL对应的emp_no记录
select employees.emp_no from employees
left join dept_manager
on employees.emp_no = dept_manager.emp_no
where dept_no is null;
方法二:使用NOT IN选出在employees但不在dept_manager中的emp_no记录
select emp_no from employees
where emp_no not in (
select emp_no from dept_manager)
不足
寻找空值的语句为:where dept_no is null
问题7
获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date=‘9999-01-01’。
结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。
CREATE TABLE dept_emp
(
emp_no
int(11) NOT NULL,
dept_no
char(4) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,dept_no
));
CREATE TABLE dept_manager
(
dept_no
char(4) NOT NULL,
emp_no
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,dept_no
));
答案
select de.emp_no,dm.emp_no AS manager_no
from dept_manager AS dm,dept_emp AS de
where de.emp_no <> dm.emp_no
and de.dept_no = dm.dept_no
and dm.to_date='9999-01-01';
解析
1.因为要输出自己的经理,得知自己与经理的部门要相同,故有限制条件 de.dept_no = dm.dept_no
2.select… from …where…可以直接连接表
3.为了增强代码可读性,将 dept_emp 用别名 de 代替,dept_manager 用 dm 代替
问题8
对应的salary
CREATE TABLE dept_emp
(
emp_no
int(11) NOT NULL,
dept_no
char(4) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,dept_no
));
CREATE TABLE salaries
(
emp_no
int(11) NOT NULL,
salary
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,from_date
));
答案
select d.dept_no, s.emp_no, max(s.salary)
from dept_emp as d,salaries as s
where d.emp_no = s.emp_no
and d.to_date = '9999-01-01'
and s.to_date = '9999-01-01'
group by dept_no
解析
1.先用INNER JOIN连接两张表,限制条件是两张表的emp_no相同,即d.emp_no = s.emp_no;
2.用GROUP BY d.dept_no将每个部门分为一组,用MAX()函数选取每组中工资最高者
20200413
问题9
题目描述
从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。
注意对于重复的emp_no进行忽略。
CREATE TABLE IF NOT EXISTS titles
(
emp_no
int(11) NOT NULL,
title
varchar(50) NOT NULL,
from_date
date NOT NULL,
to_date
date DEFAULT NULL);
答案
方法一
select title ,count(distinct emp_no) as t
from titles
group by title
having t>=2
方法二
select title,count(title) as tfrom (select distinct emp_no,title,from_date,to_date from titles )group by title having t>=2;
疑惑:
本题中,title的数=emp_no=记录数吗?
问题10
题目描述
查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列
CREATE TABLE employees
(
emp_no
int(11) NOT NULL,
birth_date
date NOT NULL,
first_name
varchar(14) NOT NULL,
last_name
varchar(16) NOT NULL,
gender
char(1) NOT NULL,
hire_date
date NOT NULL,
PRIMARY KEY (emp_no
))
答案
select * from employees
where emp_no % 2 =1
and last_name != 'Mary'
order by hire_date desc
解析:
三点需要注意:
1、员工号为奇数,则emp_no取余(%)应为1
2、last_name不为Mary,Mary 要用’’,用‘!=’或‘<>’表示
3. 根据hire_date逆序排列,用desc
问题11
题目描述
统计出当前各个title类型对应的员工当前(to_date=‘9999-01-01’)薪水对应的平均工资。结果给出title以及平均工资avg。
CREATE TABLE salaries
(
emp_no
int(11) NOT NULL,
salary
int(11) NOT NULL,
from_date
date NOT NULL,
to_date
date NOT NULL,
PRIMARY KEY (emp_no
,from_date
));
CREATE TABLE IF NOT EXISTS “titles” (
emp_no
int(11) NOT NULL,
title
varchar(50) NOT NULL,
from_date
date NOT NULL,
to_date
date DEFAULT NULL);
答案
select title ,avg(salary) as avg
from titles a inner join salaries b
on a.emp_no= b.emp_no and a.to_date= '9999-01-01' and b.to_date = '9999-01-01'
group by a.title