leetcode SQL 错题集

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 
发布了6 篇原创文章 · 获赞 0 · 访问量 331

猜你喜欢

转载自blog.csdn.net/linph174/article/details/105176849