【牛客网】数据库SQL实战(题解)
1、查找最晚入职员工的所有信息
【题解】
hire_date可能存在重复值,所以需要找到hire_date的最大值,然后再筛选,才能hire_date最晚的记录都筛选出来。
【代码】
1 SELECT * FROM employees
2 WHERE hire_date = (SELECT MAX(hire_date) FROM employees)
2、查找入职员工时间排名倒数第三的员工所有信息
【题解】
还是hire_date可能存在重复值问题,所以需要先找到第三晚的hire_date(此处排序记得用distinct去重),然后再进行筛选。
【代码】
1 SELECT * FROM employees
2 WHERE hire_date = (SELECT DISTINCT hire_date FROM employees
3 ORDER BY hire_date DESC LIMIT 2, 1)
3、查找当前薪水详情以及部门编号dept_no
【题解】
这题好坑哦,因为题目中说的是“薪水详情以及其对应部门编号dept_no”,所以salaries表是主表,要写在前面?(我对这个思路并不是很赞同)
但其实我觉得是后台没有排序问题,只要把emp_no排个序也能过。
【代码】
SELECT s.*, d.dept_no
FROM salaries s, dept_manager d
WHERE d.to_date = '9999-01-01' AND s.to_date = '9999-01-01' AND d.emp_no = s.emp_no
1 SELECT s.*, d.dept_no
2 FROM dept_manager d, salaries s
3 WHERE d.to_date = '9999-01-01' AND s.to_date = '9999-01-01' AND d.emp_no = s.emp_no
4 ORDER BY s.emp_no
4、查找所有已经分配部门的员工的last_name和first_name
【题解】
也就是说有的员工不一定被分配了部门,那么只要将部门表左连接到员工表,即部门表上的信息都会有,但部门表上没有员工表上有的信息就不会被筛出,符合题目所求。
【代码】
1 SELECT e.last_name, e.first_name, d.dept_no
2 FROM dept_emp d LEFT JOIN employees e ON e.emp_no = d.emp_no
5、查找所有员工的last_name和first_name以及对应部门编号dept_no
【题解】
跟上一题刚好反一下,这里是要把员工表左连接到部门表,这样不管员工是否有对应的部门,都能被显示出来。
【代码】
1 SELECT e.last_name, e.first_name, d.dept_no
2 FROM employees e LEFT JOIN dept_emp d ON e.emp_no = d.emp_no
6、查找所有员工入职时候的薪水情况
【题解】
这里需要注意一下,因为是给出每个员工入职时的薪资,所以还需要将加上这个条件e.hire_date = s.from_date。
【代码】
1 SELECT e.emp_no, s.salary
2 FROM employees e, salaries s
3 WHERE e.emp_no = s.emp_no AND e.hire_date = s.from_date
4 ORDER BY e.emp_no DESC
7、查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t
【题解】
GROUP BY配合聚合函数使用,按照emp_no分类后,COUNT记录每个emp_no的薪水涨幅次数,最后选出大于15的即可。
COUNT语句后面要跟HAVING哦。
如果对GROUP BY和聚合函数的使用不是很了解的话可以戳这里,我感觉讲的蛮好的。
【代码】
1 SELECT emp_no, COUNT(to_date) AS t
2 FROM salaries GROUP BY emp_no HAVING t > 15
8、找出所有员工当前薪水salary情况
【题解】
DISTINCT:如果作用于某一列,同一列的相同值只会出现一次,如果作用于所有列,那么所有列的相同值都相同才相同(可用于整张表去重)。
ORDER BY:ORDER BY col DESC 按照col列降序排,ASC为升序。
【代码】
1 SELECT DISTINCT salary
2 FROM salaries WHERE to_date = '9999-01-01'
3 ORDER BY salary DESC
9、获取所有部门当前manager的当前薪水情况
【题解】
类似第3题
【代码】
1 SELECT d.dept_no, d.emp_no, s.salary
2 FROM dept_manager d, salaries s
3 WHERE d.emp_no = s.emp_no AND d.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
10、获取所有非manager的员工emp_no
【题解】
使用NOT IN选出在employees但不在dept_manager中的emp_no记录,NOT IN的话就是顾名思义啦,“不在”的意思。
【代码】
1 SELECT e.emp_no FROM employees e
2 WHERE emp_no NOT IN(SELECT d.emp_no FROM dept_manager d)
11、获取所有员工当前的manager
【题解】
题意中明确说明如果是manager自己的话不用显示,所以需要加上这一句e.emp_no != m.emp_no,然后按要求连接两张表查询就可以啦。
【代码】
1 SELECT e.emp_no, m.emp_no AS manager_no
2 FROM dept_emp e, dept_manager m
3 WHERE e.dept_no = m.dept_no AND e.to_date = '9999-01-01'
4 AND m.to_date = '9999-01-01' AND e.emp_no != m.emp_no
12、获取所有部门中当前员工薪水最高的相关信息
【题解】
可以通过两步来理解。
第一步:通过emp_no将两个表连接,并挑选出所有部门当前员工工薪,当前是9999-01-01,题里没说,是个小bug。
第二步:因为需要给出所有部门中工薪最高的信息,所以我们按照部门分组,将最高的工薪选出来。
【代码】
1 SELECT d.dept_no, d.emp_no, s.salary
2 FROM dept_emp d, salaries s
3 WHERE d.emp_no = s.emp_no AND d.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
4 GROUP BY d.dept_no HAVING MAX(s.salary)
13、从titles表获取按照title进行分组
【题解】
第一步:根据title将表进行分组
第二步:分组后将具有相同title的记录计数,返回>=2的即可。
【代码】
1 SELECT title, COUNT(title) AS t
2 FROM titles
3 GROUP BY title HAVING t >= 2
14、从titles表获取按照title进行分组,注意对于重复的emp_no进行忽略。
【题解】
这题首先要理解清楚题目的意思,题意是想我们找到按照title分组后,每组个数大于等于2(并且其中不能包含重复的emp_no)
比如title emp_no
1 1
1 1
这样的COUNT只能算1个哦。所以还是分2步走。
第一步:按照title分组
第二步:利用DISTINCT去掉重复emp_no,然后计数。
【代码】
1 SELECT title, COUNT(DISTINCT emp_no) AS t
2 FROM titles
3 GROUP BY title HAVING t >= 2
15、查找employees表
【题解】
这题比较简单,直接按题意做就可以啦。
【代码】
1 SELECT * FROM employees
2 WHERE emp_no % 2 = 1 AND last_name != 'Mary'
3 ORDER BY hire_date DESC
16、统计出当前各个title类型对应的员工当前薪水对应的平均工资
【题解】
还是分2步来理解。
第一步:先通过emp_no将两个表连接
第二步:按照title分组,并对同属一个title的salay进行avg运算。
【代码】
1 SELECT t.title, AVG(s.salary) AS avg
2 FROM titles t, salaries s
3 WHERE t.emp_no = s.emp_no AND t.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
4 GROUP BY t.title
17、获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
【题解】
类似第二题
【代码】
1 SELECT emp_no, salary FROM salaries
2 WHERE to_date = '9999-01-01' AND salary = (
3 SELECT DISTINCT salary FROM salaries
4 ORDER BY salary DESC LIMIT 1, 1
5 )
18、获取当前薪水第二多的员工的emp_no以及其对应的薪水salary,不准使用order by
【题解】
仍然2步走。
第一步:先把两个表通过emp_no连接起来
第二步:因为这里不能用ORDER BY,所以不能再用上面的方法了,我们可以这么想,我先找出一个最大值salary,然后再找比这个最大值小的最大值,那不就是次大值了吗?
然后这里要注意题意是说当前薪水第二多的员工,所以只需s.to_date = '9999-01-01'即可。
【代码】
1 SELECT e.emp_no, MAX(s.salary), e.last_name, e.first_name
2 FROM employees e, salaries s
3 WHERE s.salary < (SELECT MAX(salary) FROM salaries
4 WHERE to_date = '9999-01-01')
5 AND e.emp_no = s.emp_no AND s.to_date = '9999-01-01'
19、查找所有员工的last_name和first_name以及对应的dept_name
【题解】
第一步:将employees表和dept_emp表通过emp_no进行左外连接,这样不管有没有分配部门的员工号对应的部门号就找出来了。
第二步:用同样的方法就讲dept_emp和departments左外连接,就能得到答案啦。
【代码】
1 SELECT e.last_name, e.first_name, dp.dept_name
2 FROM (employees e LEFT JOIN dept_emp d ON e.emp_no = d.emp_no)
3 LEFT JOIN departments dp ON d.dept_no = dp.dept_no
20、查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth
【题解】
涨幅值即薪水的最大值 - 最小值,知道这个就可以做啦。
【代码】
1 SELECT (MAX(salary) - MIN(salary)) AS growth
2 FROM salaries WHERE emp_no = '10001'
21、查找所有员工自入职以来的薪水涨幅情况
【题解】
做到这题的时候会发现,这次要求的时候所有盐工自入职以来的薪水涨幅情况,所以我们可以新建两张表。
一张是当前员工的薪水,一张是员工入职时的薪水,再将两张表连接一下排序就可以了。
【代码】
1 SELECT now.emp_no, (now.salary - pre.salary) AS growth
2 FROM (SELECT e.emp_no, s.salary FROM employees e, salaries s
3 WHERE e.emp_no = s.emp_no AND s.to_date = '9999-01-01') AS now,
4 (SELECT e.emp_no, s.salary FROM employees e, salaries s
5 WHERE e.emp_no = s.emp_no AND e.hire_date = s.from_date) AS pre
6 WHERE now.emp_no = pre.emp_no
7 ORDER BY growth ASC
22、统计各个部门对应员工涨幅的次数总和
【题解】
将三个表连接后,按照dept_no分组,计算有几条salary记录即可。
【代码】
1 SELECT dp.dept_no, dp.dept_name, COUNT(s.salary) AS sum
2 FROM departments dp, dept_emp d, salaries s
3 WHERE dp.dept_no = d.dept_no AND d.emp_no = s.emp_no
4 GROUP BY dp.dept_no
23、对所有员工的薪水按照salary进行按照1-N的排名
【题解】
这道题我觉得还是挺巧妙的,有必要收藏一下嘻嘻嘻。
首先要将两张salaries表连接,先挑选出to_date = '9999-01-01'的记录,然后注入灵魂的一句话就是s1.salary <= s2.salary,这句话是什么意思呢?比如我在s1表中找到一个salary是100,在s2中就能找到对应的大于等于100的(100,100,300)这样3条数据,然后用DISTINCT去重之后也就是2条,就是该salary的排名啦。
【代码】
1 SELECT s1.emp_no, s1.salary, COUNT(DISTINCT s2.salary) AS rank
2 FROM salaries s1, salaries s2
3 WHERE s1.to_date = '9999-01-01' AND s2.to_date = '9999-01-01' AND s1.salary <= s2.salary
4 GROUP BY s1.emp_no
5 ORDER BY s1.salary DESC, s1.emp_no ASC
24、获取所有非manager员工当前的薪水情况
【题解】
好像斌不需要用employees表?
因为我只需从salaries表中找出不属于dept_manager表的emp_no,然后让salaries表和dept_emp连接就可以得到非manager员工当前的薪水情况啦。
【代码】
1 SELECT d.dept_no, s.emp_no, s.salary
2 FROM dept_emp d, salaries s
3 WHERE s.emp_no NOT IN (SELECT emp_no FROM dept_manager) AND
4 s.emp_no = d.emp_no AND s.to_date = '9999-01-01'
25、获取员工其当前的薪水比其manager当前薪水还高的相关信息
【题解】
首先将manager表和salaries表连接成一个新表ms,emp表和salaries表也连接成一个新表es。
然后就可以根据题意操作啦,只要es.salary > ms.salary就可以了。
【代码】
1 SELECT es.emp_no, ms.emp_no AS manager_no, es.salary AS emp_salary, ms.salary AS manager_salary
2 FROM (dept_emp AS d INNER JOIN salaries AS s ON d.emp_no = s.emp_no AND s.to_date = '9999-01-01')AS es,
3 (dept_manager AS dm INNER JOIN salaries AS s ON dm.emp_no = s.emp_no AND s.to_date = '9999-01-01')AS ms
4 WHERE es.emp_no NOT IN (SELECT emp_no FROM dept_manager) AND
5 es.dept_no = ms.dept_no AND es.salary > ms.salary
26、汇总各个部门当前员工的title类型的分配数目
【题解】
这里有几个注意点。
(1)这里统计的是当前员工的当前头衔,所以t.to_date = '9999-01-01',d.to_date = '9999-01-01'
(2)分组也有两个参数,因为首先需要根据部门分组,再在部门里面根据不同的title进行分组统计。
【代码】
1 SELECT d.dept_no, dp.dept_name, t.title, COUNT(t.title) AS count
2 FROM departments dp, dept_emp d, titles t
3 WHERE dp.dept_no = d.dept_no AND d.emp_no = t.emp_no AND t.to_date = '9999-01-01'
4 AND d.to_date = '9999-01-01'
5 GROUP BY d.dept_no, t.title
27、给出每个员工每年薪水涨幅超过5000的员工编号emp_no
【题解】
设s1表为员工涨薪之前的表,s2表为员工涨薪之后的表。那么通过emp_no就可以把他们连接起来。然后这道题其实题意不是很明确,他说是每年,但事实上只要年份差为1即可。
因此只需要两个表的to_date相差1,且满足薪水涨幅超过5000就要把它选出来,另外不能忘记如果两个表的from_date相差1,也是需要被选出来的。比如有两个字段(2000-5-05,2001-6-13)和(2001-7-30,2001-8-12)也可以算是相差1年。
【代码】
1 SELECT s2.emp_no, s2.from_date, (s2.salary - s1.salary) AS salary_growth
2 FROM salaries s1, salaries s2
3 WHERE s1.emp_no = s2.emp_no
4 AND salary_growth > 5000
5 AND (strftime("%Y", s2.to_date) - strftime("%Y", s1.to_date) = 1
6 OR strftime("%Y", s2.from_date) - strftime("%Y", s1.from_date) = 1 )
7 ORDER BY salary_growth DESC
28、查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量
【题解】
这题我们可以把每个类别电影数目>=5的类别先找出来建立个虚表cc。
然后经过这几个表的连接就可以得到答案啦。
【代码】
1 SELECT c.name, COUNT(fc.film_id) AS num
2 FROM (SELECT category_id FROM film_category
3 GROUP BY category_id HAVING COUNT(film_id) >=5) AS cc,
4 film f, category c, film_category fc
5 WHERE f.description LIKE '%robot%' AND f.film_id = fc.film_id
6 AND fc.category_id = cc.category_id AND fc.category_id = c.category_id
29、使用join查询方式找出没有分类的电影id以及名称
【题解】
这题还是蛮简单的,只需要通过左连接找到有分类的电影id,然后加个NOT IN就可以了。
【代码】
1 SELECT film_id, title
2 FROM film
3 WHERE film_id NOT IN(
4 SELECT f.film_id FROM film_category AS fc LEFT JOIN film AS f ON fc.film_id = f.film_id)
30、用子查询的方式找出属于Action分类的所有电影对应的title,description
【题解】
简单题,通过WHERE...IN...将3张表连接即可。
【代码】
1 SELECT title, description FROM film
2 WHERE film_id IN (SELECT film_id FROM film_category WHERE category_id IN
3 (SELECT category_id FROM category WHERE name = 'Action'))
31、获取select * from employees对应的执行计划
【题解】
explain模拟优化器执行SQL语句,在5.6以及以后的版本中,除过select,其他比如insert,update和delete均可以使用explain查看执行计划,从而知道mysql是如何处理sql语句,分析查询语句或者表结构的性能瓶颈。
【代码】
1 EXPLAIN SELECT * FROM employees
32、将employees表的所有员工的last_name和first_name拼接起来作为Name
【题解】
MySQL、SQL Server、Oracle等数据库支持CONCAT方法,
而本题所用的SQLite数据库只支持用连接符号"||"来连接字符串
【代码】
mysql写法:
1 SELECT CONCAT(last_name, " ", first_name) AS Name FROM employees
SQLite写法:
1 SELECT last_name ||" "|| first_name AS Name FROM employees
33、创建一个actor表,包含如下列信息
【题解】
获取系统默认时间是datetime('now','localtime')
【代码】
1 CREATE TABLE actor
2 (
3 actor_id smallint(5) NOT NULL PRIMARY KEY,
4 first_name varchar(45) NOT NULL,
5 last_name varchar(45) NOT NULL,
6 last_update timestamp NOT NULL DEFAULT (datetime('now','localtime'))
7 )
34、批量插入数据
【题解】
只需要知道INSERT INTO 表名 VALUES的用法就可以啦
【代码】
1 INSERT INTO actor VALUES (1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33') ,
2 (2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33')
35、批量插入数据,不使用replace操作
【题解】
需要知道INSERT OR IGNORE INTO 表名 VALUES...
即如果数据存在就忽略不插入
【代码】
SQLite写法:
1 INSERT OR IGNORE INTO actor VALUES
2 (3, 'ED', 'CHASE', '2006-02-15 12:34:33')
Mysql写法:
1 INSERT IGNORE INTO actor VALUES
2 (3, 'ED', 'CHASE', '2006-02-15 12:34:33')
36、创建一个actor_name表
【题解】
把查询到的内容建表!get√
【代码】
SQLite写法:
1 CREATE TABLE actor_name AS
2 SELECT first_name, last_name FROM actor
MySQL写法:
1 CREATE TABLE actor_name
2 SELECT first_name, last_name FROM actor
37、对first_name创建唯一索引uniq_idx_firstname
【题解】
添加索引的两种方式:(不知道为啥这题第二种过不了)
①修改表:ALTER TABLE 表名 ADD (UNIQUE) INDEX ON 索引名(属性名)
②创建索引:CREATE (UNIQUE) INDEX 索引名 ON 表名(属性名)
【代码】
1 CREATE UNIQUE INDEX uniq_idx_firstname ON actor(first_name);
2 CREATE INDEX idx_lastname ON actor(last_name);
3
4 //
5 ALTER TABLE actor ADD UNIQUE INDEX uniq_idx_firstname(first_name);
6 ALTER TABLE actor ADD INDEX idx_lastname(last_name);
38、针对actor表创建视图actor_name_view
【题解】
创建视图:CREATE VIEW 视图名 AS ...
【代码】
1 CREATE VIEW actor_name_view AS
2 SELECT first_name AS first_name_v, last_name AS last_name_v
3 FROM actor
39、针对上面的salaries表emp_no字段创建索引idx_emp_no
【题解】
SQLite中,使用INDEXED语句进行强制索引查询:
SELECT * FROM salaries INDEXED BY idx_emp_no WHERE emp_no = 10005
MySQL中,使用 FORCE INDEX 语句进行强制索引查询:
SELECT * FROM salaries FORCE INDEX idx_emp_no WHERE emp_no = 10005
【代码】
1 SELECT * FROM salaries
2 INDEXED BY idx_emp_no WHERE emp_no = '10005'
40、在last_update后面新增加一列名字为create_date
【题解】
修改表结构:ARTER TABLE 表名
添加列:ADD COLUMN 列名 ...
删除列:DROP COLUMN 列名
修改列:CHANGE COLUMN 列名 新列名...
【代码】
1 ALTER TABLE actor
2 ADD COLUMN create_date datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
【牛客网】数据库SQL实战(题解)的更多相关文章
- 牛客网数据库SQL实战解析(51-61题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- 牛客网数据库SQL实战解析(31-40题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- 牛客网数据库SQL实战解析(21-30题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- 牛客网数据库SQL实战解析(11-20题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- 牛客网数据库SQL实战解析(1-10题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- 牛客网数据库SQL实战解析(41-50题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- 牛客网数据库SQL实战(此处只有答案,没有表内容)
1.查找最晚入职员工的所有信息 select * from employees order by hire_date desc limit 1; --limit n表示输出前n条数据,limit ...
- 牛客网数据库SQL实战(21-25)
21.查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序CREATE TABLE `employees` (`emp_no` i ...
- 牛客网数据库SQL实战(16-20)
16.统计出当前各个title类型对应的员工当前薪水对应的平均工资.结果给出title以及平均工资avg.CREATE TABLE `salaries` (`emp_no` int(11) NOT N ...
- 牛客网数据库SQL实战(11-15)
11.获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'.结果第一列给出当前员工的emp_no,第二列给出其manager ...
随机推荐
- H5 CSS 悬浮滚动条
H5 CSS 悬浮滚动条 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- Huffman coding & Huffman tree
Huffman coding & Huffman tree Huffman coding 哈夫曼编码 / 最优二元前缀码 Huffman tree 哈夫曼树 / 最优二叉树 https://w ...
- iOS remote debug & Android remote debug & Chrome & APP
iOS remote debug & Android remote debug & Chrome & APP iOS remote debugging 如何在 iOS 真机上调 ...
- React & Didact
React & Didact A DIY guide to build your own React https://github.com/pomber/didact https://gith ...
- MongoDB的下载、安装与部署
1.什么是MongoDB? 它是介于关系型数据库和非关系型数据库之间的一种NoSQL数据库,用C++编写,是一款集敏捷性.可伸缩性.扩展性于一身的高性能的面向文档的通用数据库. 2.为什么要用Mong ...
- 调整是为了更好的上涨,牛市下的SPC空投来了!
2021年刚过没几天,比特币就开启了牛市的旅程,BTC涨到4万美元,ETH涨到1300多美元,BGV也涨到了621.05美元,牛市已然来袭. 虽然从近两日,比特币带领着主流币进行了一波调整,但是只涨不 ...
- 专注于大数据分析和数字基建,星盟UICI切入资产管理领域
资产管理行业体系庞大,按领域可以大致分为公募.私募.券商.保险.银行.信托六大领域.面对六大领域百万亿级市场,近年来,也出现了不少初创公司针对资产管理的细分领域提供专有解决方案.而星盟全球投资公司就是 ...
- LoveWord
个人喜欢的句子汇总! 我告诉你我喜欢你,并不是一定要和你在一起,只是希望今后的你,在遭遇人生低谷的时候,不要灰心,至少曾经有人被你的魅力所吸引,曾经是,以后也会是----村上村树
- MySQL -- 内部临时表
本文转载自MySQL -- 内部临时表 UNION UNION语义:取两个子查询结果的并集,重复的行只保留一行 表初始化 CREATE TABLE t1(id INT PRIMARY KEY, a I ...
- 进阶高阶IoT架构-教你如何简单实现一个消息队列
前言 消息队列是软件系统领域用来实现系统间通信最广泛的中间件.基于消息队列的方式是指由应用中的某个系统负责发送消息,由关心这条消息的相关系统负责接收消息,并在收到消息后进行各自系统内的业务处理.消息可 ...