题目来源:https://www.nowcoder.com/ta/sql
本文挑选了牛客OJ SQL比较典型的题目,有些题目为什么没写?那些重复性的,有些题目描述就不清楚的,看了讨论区也讲不清的,就没做。
OJ系统的判题只支持SQLite,以下答案皆为SQLite。
题目描述后面的标题是笔者自己简化的,为了体现题目重点。

想尝试一下用折叠把答案折叠起来的,好像CSDN的markdown不支持?

题目 拼接

将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分

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`));

输出描述:
Name

         Facello GeorgiSimmel BezalelBamford PartoKoblick Chirstian

解答

SELECT last_name || ' ' || first_name AS Name
FROM employees;

题目 创建

创建一个actor表,包含如下列信息
列表 类型 是否为NULL 含义
actor_id smallint(5) not null 主键id
first_name varchar(45) not null 名字
last_name varchar(45) not null 姓氏
last_update timestamp not null 最后更新时间,默认是系统的当前时间

解答

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 timestamp NOT NULL DEFAULT (datetime('now','localtime')) -- ,
-- PRIMARY KEY(actor_id)
)

题目 批量插入数据

对于表actor批量插入如下数据

CREATE TABLE IF NOT EXISTS actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')))

actor_id first_name last_name last_update
1 PENELOPE GUINESS 2006-02-15 12:34:33
2 NICK WAHLBERG 2006-02-15 12:34:33

解答

INSERT INTO actor
VALUES(1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'),(2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33');

题目 批量插入不使用replace操作

对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作

CREATE TABLE IF NOT EXISTS actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')))

actor_id first_name last_name last_update
‘3’ ‘ED’ ‘CHASE’ ‘2006-02-15 12:34:33’

解答

INSERT OR IGNORE INTO actor VALUES (3, 'ED', 'CHASE', '2006-02-15 12:34:33')

题目 导入到新表

对于如下表actor,其对应的数据为:
actor_id first_name last_name last_update
1 PENELOPE GUINESS 2006-02-15 12:34:33
2 NICK WAHLBERG 2006-02-15 12:34:33

创建一个actor_name表,将actor表中的所有first_name以及last_name导入改表。 actor_name表结构如下:
列表 类型 是否为NULL 含义
first_name varchar(45) not null 名字
last_name varchar(45) not null 姓氏

解答

CREATE TABLE actor_name AS
SELECT first_name,last_name FROM actor;

题目 唯一索引

针对如下表actor结构创建索引:

CREATE TABLE IF NOT EXISTS actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')))

对first_name创建唯一索引uniq_idx_firstname,对last_name创建普通索引idx_lastname

解答

CREATE UNIQUE INDEX uniq_idx_firstname on actor(first_name);
CREATE INDEX idx_lastname on actor(last_name);

题目 创建视图

针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v:

CREATE TABLE IF NOT EXISTS actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')))

解答

CREATE VIEW actor_name_view (first_name_v, last_name_v) AS
SELECT first_name, last_name FROM actor;

题目 强制索引

针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引。

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 index idx_emp_no on salaries(emp_no);

解答

MYSQL中强制索引查询使用:FORCE INDEX(indexname);
SQLite中强制索引查询使用:INDEXED BY indexname;

SELECT * FROM salaries INDEXED BY idx_emp_no WHERE emp_no = 10005;

题目 增加列

存在actor表,包含如下列信息:

CREATE TABLE IF NOT EXISTS actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')));

现在在last_update后面新增加一列名字为create_date, 类型为datetime, NOT NULL,默认值为’0000 00:00:00’

解答

ALTER table actor
ADD 'create_date' datetime NOT NULL DEFAULT '0000-00-00 00:00:00';

题目 触发器

构造一个触发器audit_log,在向employees_test表中插入一条数据的时候,触发插入相关的数据到audit中。

CREATE TABLE employees_test(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);
CREATE TABLE audit(
EMP_no INT NOT NULL,
NAME TEXT NOT NULL
);

解答

CREATE TRIGGER audit_log AFTER INSERT ON employees_test
BEGININSERT INTO audit VALUES (NEW.ID, NEW.NAME);
END;

题目 删除重复行

删除emp_no重复的记录,只保留最小的id对应的记录。

CREATE TABLE IF NOT EXISTS 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');

解答

DELETE FROM titles_test
WHERE id NOT IN (SELECT * FROM(SELECT MIN(id) FROM titles_test GROUP BY emp_no
) AS a);

题目 更新行中多个元素

将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。

CREATE TABLE IF NOT EXISTS 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');

解答

UPDATE titles_test SET to_date = NULL, from_date = '2001-01-01'
WHERE to_date = '9999-01-01';

题目 使用REPLACE INTO

将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。

CREATE TABLE IF NOT EXISTS 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');

解答

REPLACE INTO的效果:有则更新,无则插入

REPLACE INTO titles_test VALUES (5, 10005, 'Senior Engineer', '1986-06-26', '9999-01-01');

题目 创建外键约束

在audit表上创建外键约束,其emp_no对应employees_test表的主键id。

CREATE TABLE employees_test(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);CREATE TABLE audit(
EMP_no INT NOT NULL,
create_date datetime NOT NULL
);

解答

由于SQLite中不能通过 ALTER TABLE … ADD FOREIGN KEY … REFERENCES … 语句来对已创建好的字段创建外键,因此只能先删除表,再重新建表的过程中创建外键。

DROP TABLE audit;CREATE TABLE audit(EMP_no INT NOT NULL,create_date datetime NOT NULL,FOREIGN KEY(EMP_no) REFERENCES employees_test(ID));

题目 JOIN

将所有获取奖金的员工当前的薪水增加10%。

create table emp_bonus(
emp_no int not null,
recevied datetime not null,
btype smallint not null);
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`));

解答

UPDATE salaries SET salary = salary * 1.1 WHERE emp_no IN
(SELECT s.emp_no FROM salaries AS s INNER JOIN emp_bonus AS eb
ON s.emp_no = eb.emp_no AND s.to_date = '9999-01-01');

题目 字符串相关函数(1)

查找字符串’10,A,B’ 中逗号’,'出现的次数cnt。

解答

SELECT length('10,A,B') -length(REPLACE('10,A,B',",",""))

题目 字符串相关函数(2)

获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列

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`));

输出格式:
first_name

Chirstian
Tzvetan
Bezalel
Duangkaew
Georgi
Kyoichi
Anneke
Sumant
Mary
Parto
Saniya

解答

SELECT first_name FROM employees
ORDER BY substr(first_name,length(first_name)-1,2);

题目 MAX() MIN() AVG()

查找排除当前最大、最小salary之后的员工的平均工资avg_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`));

输出格式:
avg_salary
69462.5555555556

解答

参考讨论区的解答:本题逻辑有问题,在挑选当前最大、最小salary时没加 to_date = ‘9999-01-01’ 作条件限制,导致挑选出来的是全表最大、最小salary,然后对除去这两个salary再作条件限制 to_date = ‘9999-01-01’ ,求平均薪水,此时求出的平均薪水与题目逻辑要求的不同。
链接:https://www.nowcoder.com/questionTerminal/95078e5e1fba4438b85d9f11240bc591?f=discussion

SELECT AVG(salary) AS avg_salary FROM salaries
WHERE to_date = '9999-01-01'
AND salary NOT IN (SELECT MAX(salary) FROM salaries)
AND salary NOT IN (SELECT MIN(salary) FROM salaries);

题目 LIMIT OFFSET

分页查询employees表,每5行一页,返回第2页的数据

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 LIMIT 5 OFFSET 5;

题目 LEFT JOIN

获取所有员工的emp_no、部门编号dept_no以及对应的bonus类型btype和received ,没有分配具体的员工不显示

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`));
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`));
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 emp_bonus(
emp_no int not null,
recevied datetime not null,
btype smallint not null);

输出格式:
e.emp_no dept_no btype received
10001 d001 1 2010-01-01
10002 d001 2 2010-10-01
10003 d004 3 2011-12-03
10004 d004 1 2010-01-01
10005 d003
10006 d002
10007 d005
10008 d005
10009 d006
10010 d005
10010 d006

解答

SELECT de.emp_no, de.dept_no, eb.btype, eb.recevied
FROM dept_emp AS de LEFT JOIN emp_bonus AS eb
ON de.emp_no = eb.emp_no;

题目 EXISTS

使用含有关键字exists查找未分配具体部门的员工的所有信息。

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`));
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`));

输出格式:
emp_no birth_date first_name last_name gender hire_date
10011 1953-11-07 Mary Sluis F 1990-01-22

解答

SELECT * FROM employees WHERE NOT EXISTS
(SELECT emp_no FROM dept_emp WHERE emp_no = employees.emp_no);

题目 CASE条件

获取有奖金的员工相关信息。

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`));
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 emp_bonus(
emp_no int not null,
recevied datetime not null,
btype smallint not null);
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`));

给出emp_no、first_name、last_name、奖金类型btype、对应的当前薪水情况salary以及奖金金额bonus。 bonus类型btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%。 当前薪水表示to_date=‘9999-01-01’
输出格式:
emp_no first_name last_name btype salary bonus
10001 Georgi Facello 1 88958 8895.8
10002 Bezalel Simmel 2 72527 14505.4
10003 Parto Bamford 3 43311 12993.3
10004 Chirstian Koblick 1 74057 7405.7

解答

SELECT e.emp_no, e.first_name, e.last_name, b.btype, s.salary,
(CASE b.btype WHEN 1 THEN s.salary * 0.1WHEN 2 THEN s.salary * 0.2ELSE s.salary * 0.3 END) AS bonus
FROM employees AS e INNER JOIN emp_bonus AS b ON e.emp_no = b.emp_no
INNER JOIN salaries AS s ON e.emp_no = s.emp_no AND s.to_date = '9999-01-01';

题目 窗口函数

按照salary的累计和running_total,其中running_total为前两个员工的salary累计和,其他以此类推。 具体结果如下Demo展示

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`));

输出格式:
emp_no salary running_total
10001 88958 88958
10002 72527 161485
10003 43311 204796
10004 74057 278853
10005 94692 373545
10006 43311 416856
10007 88070 504926
10009 95409 600335
10010 94409 694744
10011 25828 720572

解答

题干表述有误,running_total给出的应该是前面所有员工的salary之和。
答案要加上to_date的条件是因为:一个人的工资可能有多条记录,9999-01-01对应的记录则是最新的记录。
参考别人的解答,把sum聚合函数作为窗口函数使用,所有聚合函数都能用做窗口函数,其语法和专用窗口函数完全相同。

SUM(<汇总列>) OVER(<排序列>) AS 别名;

答案:

SELECT emp_no,salary,
SUM(salary) over(ORDER BY emp_no) AS running_total
FROM salaries
WHERE to_date= '9999-01-01';

牛客OJ SQL后30题的解答相关推荐

  1. 牛客网SQL大厂真题二刷小白白话总结(二)用户增长场景(某度信息流)

    二.用户增长场景(某度信息流) 目录 二.用户增长场景(某度信息流) SQL7 2021年11月每天的人均浏览文章时长(简单) SQL8 每篇文章同一时刻最大在看人数(中等) SQL9 2021年11 ...

  2. 牛客网SQL篇刷题篇(16-23)

    https://www.nowcoder.com/ta/sql 1.SQL嵌套查询 https://www.cnblogs.com/glassysky/p/11559082.html (1)什么是嵌套 ...

  3. 牛客网SQL大厂真题二刷小白白话总结(五)某宝店铺分析(电商模式)

    目录 SQL25 某宝店铺的SPU数量(简单) SQL26 某宝店铺的实际销售额与客单价(简单) SQL27 某宝店铺折扣率(中等) SQL28 某宝店铺动销率与售罄率(较难) SQL29 某宝店铺连 ...

  4. 牛客网SQL篇刷题篇(38-47)

    1.视图:视图是可视化的表. 视图的作用: 第一点:使用视图,可以定制用户数据,聚焦特定的数据. 解释: 在实际过程中,公司有不同角色的工作人员,我们以销售公司为例的话, 采购人员,可以需要一些与其有 ...

  5. 牛客网SQL篇刷题篇(32-37)

    https://www.nowcoder.com/ta/sql 1.sql group_contact().concat().concat_ws函数 https://blog.csdn.net/qq_ ...

  6. 牛客网SQL篇刷题篇(24-31)

    https://www.nowcoder.com/ta/sql 1.NOT IN NOT IN运算符允许从结果集中排除特定值的列表. 2.sql子查询 https://www.cnblogs.com/ ...

  7. 牛客网SQL篇刷题篇(3-10)

    https://www.nowcoder.com/ta/sql 1.inner join 和left join (1)在表中存在至少一个匹配时,INNER JOIN 关键字返回行. SELECT ** ...

  8. 牛客网SQL篇刷题篇(1-2)

    https://www.nowcoder.com/ta/sql

  9. 牛客网SQL大厂真题二刷小白白话总结(三)电商场景(某东商城)

    三.电商场景(某东商城) 目录 SQL13 计算商城中2021年每月的GMV(简单) SQL14 统计2021年10月每个退货率不大于0.5的商品各项指标(中等) SQL15 某店铺的各商品毛利率及店 ...

最新文章

  1. 雷林鹏分享:jQuery EasyUI 数据网格 - 创建属性网格
  2. 如何查询oracle死锁,Oracle死锁查看和解决办法汇总
  3. 基于curl的php多线程类(异步请求)
  4. 安装java环境linux和windows
  5. 在ubuntu下各种格式软件安装及常用命令
  6. Python嵌套列表解析式(又称列表推导式)写法剖析与应用举例
  7. [渝粤教育] 西南科技大学 工程建设监理 在线考试复习资料
  8. JavaScript中的数组创建
  9. Linux常用命令(第二版) --系统开关机命令
  10. ACOUG 联合创始人盖国强:万象更新,数据库技术和生态的发展演进
  11. 代理 设置wsl_为 WSL2 一键设置代理
  12. ubuntu 安装 man 查看函数原型
  13. iOS:简单使用UIAlertVIew和UIActionSheet
  14. javascript实现计算器
  15. 重庆北大青鸟校区【学员心声】:学习是我们前进的动力
  16. 高效工作节省时间的一些小技巧
  17. 搭建简单的企业网站,华为云速建站和阿里建站哪个好?
  18. android圆环头像,Android实现带圆环的圆形头像
  19. IE加载ocx时提示控件不安全的解决方法
  20. android应用备份,Android备份App及数据

热门文章

  1. HDU-5115-Dire Wolf
  2. 四格表求卡方示例,独立四格表资料检验,统计学,差异性分析
  3. 微信公众平台开发四六级成绩查询
  4. 5G?折叠屏?华为新款手机刷屏了!
  5. 抖音、快手、脸书陷舆论漩涡,CEO纷纷致歉,AI算法不灵了?
  6. 服部周作《麦肯锡晋升法则》读书笔记 I
  7. Java集合框架笔记,足够深,足够全面
  8. Android 7.0新特性——长按出现快捷方式
  9. access如何查询两张表的内容_Access使用技术2:使用交叉表查询向导进行每日汇总...
  10. Linux系统编程-进程概念、进程管理、信号处理