【SQL】 牛客网SQL训练Part1 简单难度
地址位置:
https://www.nowcoder.com/exam/oj?difficulty=2
查找入职员工时间排名倒数第三的员工所有信息
-- 准备脚本 drop table if exists `employees` ; 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`)); INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26'); INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21'); INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28'); INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01'); INSERT INTO employees VALUES(10005,'1955-01-21','Kyoichi','Maliniak','M','1989-09-12'); INSERT INTO employees VALUES(10006,'1953-04-20','Anneke','Preusig','F','1989-06-02'); INSERT INTO employees VALUES(10007,'1957-05-23','Tzvetan','Zielinski','F','1989-02-10'); INSERT INTO employees VALUES(10008,'1958-02-19','Saniya','Kalloufi','M','1994-09-15'); INSERT INTO employees VALUES(10009,'1952-04-19','Sumant','Peac','F','1985-02-18'); INSERT INTO employees VALUES(10010,'1963-06-01','Duangkaew','Piveteau','F','1989-08-24'); INSERT INTO employees VALUES(10011,'1953-11-07','Mary','Sluis','F','1990-01-22'); -- 按默认的情况筛选 SELECT * FROM `employees` ORDER BY hire_date DESC LIMIT 2, 1 -- 如果时间存在多个同样的,去重处理后再查询 SELECT * FROM employees WHERE hire_date = ( SELECT DISTINCT hire_date FROM employees ORDER BY hire_date DESC -- 倒序 LIMIT 1 OFFSET 2 -- 去掉排名倒数第一第二的时间,取倒数第三 );
查找所有已经分配部门的员工的last_name和first_name以及dept_no
drop table if exists `dept_emp` ; drop table if exists `employees` ; 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 `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`)); INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01'); INSERT INTO dept_emp VALUES(10002,'d002','1996-08-03','9999-01-01'); INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26'); INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21'); INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28'); INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01'); -- 查询SQL SELECT A.last_name, A.first_name, B.dept_no FROM employees AS A LEFT JOIN dept_emp AS B ON A.emp_no = B.emp_no WHERE B.DEPT_NO IS NOT NULL
查找薪水记录超过15条的员工号emp_no以及其对应的记录次数t
drop table if exists `salaries` ; 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`)); INSERT INTO salaries VALUES(10001,60117,'1986-06-26','1987-06-26'); INSERT INTO salaries VALUES(10001,62102,'1987-06-26','1988-06-25'); INSERT INTO salaries VALUES(10001,66074,'1988-06-25','1989-06-25'); INSERT INTO salaries VALUES(10001,66596,'1989-06-25','1990-06-25'); INSERT INTO salaries VALUES(10001,66961,'1990-06-25','1991-06-25'); INSERT INTO salaries VALUES(10001,71046,'1991-06-25','1992-06-24'); INSERT INTO salaries VALUES(10001,74333,'1992-06-24','1993-06-24'); INSERT INTO salaries VALUES(10001,75286,'1993-06-24','1994-06-24'); INSERT INTO salaries VALUES(10001,75994,'1994-06-24','1995-06-24'); INSERT INTO salaries VALUES(10001,76884,'1995-06-24','1996-06-23'); INSERT INTO salaries VALUES(10001,80013,'1996-06-23','1997-06-23'); INSERT INTO salaries VALUES(10001,81025,'1997-06-23','1998-06-23'); INSERT INTO salaries VALUES(10001,81097,'1998-06-23','1999-06-23'); INSERT INTO salaries VALUES(10001,84917,'1999-06-23','2000-06-22'); INSERT INTO salaries VALUES(10001,85112,'2000-06-22','2001-06-22'); INSERT INTO salaries VALUES(10001,85097,'2001-06-22','2002-06-22'); INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01'); INSERT INTO salaries VALUES(10002,72527,'1996-08-03','1997-08-03'); -- GROUP BY + HAVING 筛选 SELECT `emp_no`, COUNT(`emp_no`) AS `t` FROM `salaries` GROUP BY `emp_no` HAVING `t` > 15
找出所有员工当前薪水salary情况
drop table if exists `salaries` ; 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`)); INSERT INTO salaries VALUES(10001,72527,'2002-06-22','9999-01-01'); INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01'); INSERT INTO salaries VALUES(10003,43311,'2001-12-01','9999-01-01'); -- 对这个薪资进行去重即可 SELECT DISTINCT `salary` FROM `salaries` ORDER BY `salary` DESC
获取所有非manager的员工emp_no
drop table if exists `dept_manager` ; drop table if exists `employees` ; 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`)); INSERT INTO dept_manager VALUES('d001',10002,'1996-08-03','9999-01-01'); INSERT INTO dept_manager VALUES('d002',10003,'1990-08-05','9999-01-01'); INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26'); INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21'); INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28'); -- 按员工表作为主表,联表,筛选条件为 部门号为空的记录 SELECT A.emp_no FROM `employees` AS A LEFT JOIN `dept_manager` AS B ON A.emp_no = B.emp_no WHERE B.dept_no IS NULL
查找employees表emp_no与last_name的员工信息
请你查找
1、employees表所有emp_no为奇数,
2、且last_name不为Mary的员工信息,
3、并按照hire_date逆序排列,
drop table if exists `employees` ; 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`)); INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26'); INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21'); INSERT INTO employees VALUES(10003,'1959-12-03','Bezalel','Mary','M','1986-08-28'); INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01'); INSERT INTO employees VALUES(10005,'1953-11-07','Mary','Sluis','F','1990-01-22'); -- 按条件写SQL查询 SELECT * FROM employees WHERE `emp_no` MOD 2 != 0 AND `last_name` != 'Mary' ORDER BY `hire_date` DESC
获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
drop table if exists `salaries` ; 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`)); INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01'); INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01'); INSERT INTO salaries VALUES(10003,43311,'2001-12-01','9999-01-01'); -- 按薪资倒序 SELECT `emp_no`, `salary` FROM `salaries` ORDER BY `salary` DESC LIMIT 1, 1
将employees表的所有员工的last_name和first_name拼接起来作为Name
drop table if exists `employees` ; 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`)); INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26'); INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21'); INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28'); INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01'); INSERT INTO employees VALUES(10005,'1955-01-21','Kyoichi','Maliniak','M','1989-09-12'); INSERT INTO employees VALUES(10006,'1953-04-20','Anneke','Preusig','F','1989-06-02'); INSERT INTO employees VALUES(10007,'1957-05-23','Tzvetan','Zielinski','F','1989-02-10'); INSERT INTO employees VALUES(10008,'1958-02-19','Saniya','Kalloufi','M','1994-09-15'); INSERT INTO employees VALUES(10009,'1952-04-19','Sumant','Peac','F','1985-02-18'); INSERT INTO employees VALUES(10010,'1963-06-01','Duangkaew','Piveteau','F','1989-08-24'); INSERT INTO employees VALUES(10011,'1953-11-07','Mary','Sluis','F','1990-01-22'); -- CONCAT 合并函数 SELECT CONCAT(`last_name`, ' ', `first_name`) AS `Name` FROM `employees`
批量插入数据
DROP TABLE if exists actor; CREATE TABLE actor ( actor_id smallint(5) NOT NULL PRIMARY KEY, first_name varchar(45) NOT NULL, last_name varchar(45) NOT NULL, last_update DATETIME NOT NULL ); -- 插入SQL INSERT INTO `actor`VALUES (1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'), (2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33');
删除emp_no重复的记录,只保留最小的id对应的记录。
DROP TABLE if exists titles_test; CREATE TABLE titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL, title varchar(50) NOT NULL, from_date date NOT NULL, to_date date DEFAULT NULL); insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); -- 1、按员工编号分组Group筛选唯一记录,并按照最小主键值筛选, -- 2、删除时进行取反获取重复记录 -- 3、删除表时查询不能再声明是这张表,需要设置别名 DELETE FROM `titles_test` WHERE `id` NOT IN( SELECT * FROM ( SELECT MIN(`id`) FROM `titles_test` GROUP BY emp_no ) AS `tt` );
将所有to_date为9999-01-01的全部更新为NULL
1、将所有to_date为9999-01-01的全部更新为NULL,
2、且 from_date更新为2001-01-01。
DROP TABLE IF EXISTS titles_test; CREATE TABLE titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL, title varchar(50) NOT NULL, from_date date NOT NULL, to_date date DEFAULT NULL); insert into values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); -- 更新记录 UPDATE `titles_test` SET `to_date` = NULL, `from_date` = '2001-01-01' WHERE `to_date` = '9999-01-01'
将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005
其他数据保持不变,使用replace实现,直接使用update会报错。drop table if exists titles_test; CREATE TABLE titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL, title varchar(50) NOT NULL, from_date date NOT NULL, to_date date DEFAULT NULL); insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); -- 1、主键重复警告风险 Duplicate entry '5' for key 'titles_test.PRIMARY' UPDATE `titles_test` SET `id` = 5, `emp_no` = 10005 WHERE `id` = 5 AND `emp_no` = 10001 -- 2、使用Replace函数更新? UPDATE `titles_test` SET `emp_no` = REPLACE(`emp_no`, 10001, 10005) WHERE `id` = 5; -- 3、ON DUPLICATE KEY UPDATE 主键冲突触发更新 INSERT INTO titles_test VALUES(5, 10001 ,'Senior Engineer', '1986-06-26', '9999-01-01') ON DUPLICATE KEY UPDATE emp_no = 10005; -- 4、遇到主键冲突时,优先进行UPDATE操作 REPLACE INTO titles_test VALUES(5, 10005 ,'Senior Engineer', '1986-06-26', '9999-01-01') ;
将titles_test表名修改为titles_2017
drop table if exists titles_test; drop table if exists titles_2017; CREATE TABLE titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL, title varchar(50) NOT NULL, from_date date NOT NULL, to_date date DEFAULT NULL); insert into values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); -- ALTER TABLE 语法 ALTER TABLE `titles_test` RENAME TO `titles_2017`;
出现三次以上相同积分的情况
drop table if exists grade; CREATE TABLE `grade` ( `id` int(4) NOT NULL, `number` int(4) NOT NULL, PRIMARY KEY (`id`)); INSERT INTO grade VALUES (1,111), (2,333), (3,111), (4,111), (5,333); -- 分组后筛选即可 SELECT `number` FROM `grade` GROUP BY `number` HAVING COUNT(`number`) > 2
找到每个人的任务
drop table if exists person; drop table if exists task; CREATE TABLE `person` ( `id` int(4) NOT NULL, `name` varchar(32) NOT NULL, PRIMARY KEY (`id`)); CREATE TABLE `task` ( `id` int(4) NOT NULL, `person_id` int(4) NOT NULL, `content` varchar(32) NOT NULL, PRIMARY KEY (`id`)); INSERT INTO person VALUES (1,'fh'), (2,'tm'); INSERT INTO task VALUES (1,2,'tm works well'), (2,2,'tm works well'); SELECT `p`.`id`, `p`.`name`, `t`.`content` FROM `person` AS `p` LEFT JOIN `task` AS `t` ON `t`.person_id = `p`.`id`
每个人最近的登录日期
drop table if exists login; drop table if exists user; drop table if exists client; CREATE TABLE login ( id int(4) NOT NULL, user_id int(4) NOT NULL, client_id int(4) NOT NULL, date date NOT NULL, PRIMARY KEY (id)); CREATE TABLE user ( id int(4) NOT NULL, name varchar(32) NOT NULL, PRIMARY KEY (id)); CREATE TABLE client ( id int(4) NOT NULL, name varchar(32) NOT NULL, PRIMARY KEY (id)); INSERT INTO login VALUES (1,2,1,'2020-10-12'), (2,3,2,'2020-10-12'), (3,2,2,'2020-10-13'), (4,3,2,'2020-10-13'); INSERT INTO user VALUES (1,'tm'), (2,'fh'), (3,'wangchao'); INSERT INTO client VALUES (1,'pc'), (2,'ios'), (3,'anroid'), (4,'h5'); SELECT * FROM login -- 按用户ID进行分组,取日期最大值(即最近一次登录时间) select user_id,MAX(date) as recent_login_date from login group by user_id order by user_id;
考试分数
第1行表示用户id为1的用户选择了C++岗位并且考了11001分
。。。
第8行表示用户id为8的用户选择了JS岗位并且考了9999分
请你写一个sql语句查询各个岗位分数的平均数,并且按照分数降序排序,
结果保留小数点后面3位(3位之后四舍五入):
drop table if exists grade; CREATE TABLE grade( `id` int(4) NOT NULL, `job` varchar(32) NOT NULL, `score` int(10) NOT NULL, PRIMARY KEY (`id`)); INSERT INTO grade VALUES (1,'C++',11001), (2,'C++',10000), (3,'C++',9000), (4,'Java',12000), (5,'Java',13000), (6,'JS',12000), (7,'JS',11000), (8,'JS',9999); -- 对job进行分组,然后取成绩平均值,并设置四舍五入 SELECT `job`, ROUND(AVG(`score`), 3) AS `AVG_SCORE` FROM `grade` GROUP BY `job` ORDER BY `AVG_SCORE` DESC
课程订单分析:
请你写出一个sql语句查询
1、在2025-10-15以后
2、状态为购买成功的C++课程或者Java课程或者Python的订单,
3、并且按照order_info的id升序排序
drop table if exists order_info; CREATE TABLE order_info ( id int(4) NOT NULL, user_id int(11) NOT NULL, product_name varchar(256) NOT NULL, status varchar(32) NOT NULL, client_id int(4) NOT NULL, date date NOT NULL, PRIMARY KEY (id)); INSERT INTO order_info VALUES (1,557336,'C++','no_completed',1,'2025-10-10'), (2,230173543,'Python','completed',2,'2025-10-12'), (3,57,'JS','completed',3,'2025-10-23'), (4,57,'C++','completed',3,'2025-10-23'), (5,557336,'Java','completed',1,'2025-10-23'), (6,557336,'Python','no_completed',1,'2025-10-24'); -- 按描述条件查询即可 SELECT * FROM `order_info` WHERE `date` > '2025-10-15' AND `product_name` IN ('C++', 'Java', 'Python') AND `status` = 'completed' ORDER BY `id` ASC
简历分析:
写出SQL语句查询在2025年内投递简历的岗位和数量,并且按数量降序排序
drop table if exists resume_info; CREATE TABLE resume_info ( id int(4) NOT NULL, job varchar(64) NOT NULL, date date NOT NULL, num int(11) NOT NULL, PRIMARY KEY (id)); INSERT INTO resume_info VALUES (1,'C++','2025-01-02',53), (2,'Python','2025-01-02',23), (3,'Java','2025-01-02',12), (4,'Java','2025-02-03',24), (5,'C++','2025-02-03',23), (6,'Python','2025-02-03',34), (7,'Python','2025-03-04',54), (8,'C++','2025-03-04',65), (9,'Java','2025-03-04',92), (10,'Java','2026-01-04',230); -- 1、使用YEAR函数筛选25年内的数据 -- 2、再对job分组,求和NUM字段 SELECT `job`, SUM(`NUM`) AS `cnt` FROM `resume_info` WHERE YEAR(`date`) = 2025 GROUP BY `job` ORDER BY `cnt` DESC