「牛客网SQL实战二刷」是个系列学习笔记博文,每天解析6道SQL题目~ 今天是第43- 48题。
每篇笔记的格式大致为,三大板块:
「往期回顾」❤️
《牛客网SQL实战二刷 | 完整解析 – 目录索引》
题号 | 知识点 |
---|---|
43 | 更新表 UPDATE … SET … |
44 | 更新表 UPDATE … SET …,REPLACE()函数 |
45 | 修改表名 ALTER TABLE … RENAME TO … |
46 | 创建外键约束 FOREIGN KEY … REFERENCES … |
47 | INTERSECT |
48 | 更新表 UPDATE … SET … |
43. 将所有to_date为9999-01-01的全部更新为NULL
将所有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'
to_date = NULL 和 from_date = ‘2001-01-01’ 之间,应当用 逗号连接。
若以and连接,逻辑运算符优先于比较运算符,语句会变成
UPDATE titles_test SET to_date = (NULL and from_date = '2001-01-01')
《京东2018秋招数据分析工程师笔试题》 第2题。
?UPDATE 语句语法
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
《Update 语句》 http://www.w3school.com.cn/sql/sql_update.asp
44. 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005
将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');
UPDATE titles_test SET emp_no = REPLACE(emp_no, 10001, 10005) WHERE id = 5 AND emp_no = 10001
# 利用题目漏洞,不用REPLACE()
UPDATE titles_test SET emp_no = 10005 WHERE id = 5 AND emp_no = 10001
?REPLACE(X,Y,Z)函数
- replace(X,Y,Z)
X:要处理的字符串
Y:被替换的字符串
Z:替换后的字符串
《Sqlite数据库字符串处理函数replace》https://www.cnblogs.com/huangtailang/p/5cfbd242cae2bcc929c81c266d0c875b.html
45. 将titles_test表名修改为titles_2017
将titles_test表名修改为titles_2017。
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');
ALTER TABLE titles_test RENAME TO titles_2017
?ALTER TABLE 语法
ALTER TABLE database_name.table_name RENAME TO new_table_name;
《SQLite Alter 命令》https://www.runoob.com/sqlite/sqlite-alter-command.html
46. 在audit表上创建外键约束,其emp_no对应employees_test表的主键id
在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));
-- SQLite 中设置外键还可以用以下方法,
-- 但由于本题 OJ 系统检测机制不完善导致不通过:
DROP TABLE audit;
CREATE TABLE audit(
EMP_no INT NOT NULL REFERENCES employees_test(ID),
create_date datetime NOT NULL);
来源:https://www.nowcoder.com/questionTerminal/aeaa116185f24f209ca4fa40e226de48
?SQL FOREIGN KEY 约束
(以下均为MySQL的语法,其他语言的语法详见参考资料)
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
-- 当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束,请使用下面的 SQL:
ALTER TABLE Orders
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
ALTER TABLE Orders
DROP FOREIGN KEY fk_PerOrders
《SQL FOREIGN KEY 约束》https://www.runoob.com/sql/sql-foreignkey.html
47. 如何获取emp_v和employees有相同的数据no
存在如下的视图:
create view emp_v as select * from employees where emp_no >10005;
如何获取emp_v和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`));
emp_no | birth_date | first_name | last_name | gender | hire_date |
---|---|---|---|---|---|
10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 |
10007 | 1957-05-23 | Tzvetan | Zielinski | F | 1989-02-10 |
10008 | 1958-02-19 | Saniya | Kalloufi | M | 1994-09-15 |
10009 | 1952-04-19 | Sumant | Peac | F | 1985-02-18 |
10010 | 1963-06-01 | Duangkaew | Piveteau | F | 1989-08-24 |
10011 | 1953-11-07 | Mary | Sluis | F | 1990-01-22 |
1. 方法一:
- 由于视图 emp_v 的记录是从 employees 中导出的,所以要判断两者中相等的数据,只需要判断emp_no相等即可。
- 思路:用 WHERE 选取二者 emp_no 相等的记录
SELECT em.* FROM employees AS em, emp_v AS ev WHERE em.emp_no = ev.emp_no
2. 方法二:
- 思路:用 INTERSECT 关键字求 employees 和 emp_v 的交集
SELECT * FROM emp_v INTERSECT SELECT * FROM employees
3. 方法三:
- 思路:仔细一想,emp_v的全部记录均由 employees 导出,因此可以投机取巧,直接输出 emp_v 所有记录
SELECT * FROM emp_v
【错误方法】
- 用以下方法直接输出 *,会得到两张表中符合条件的重复记录,因此不合题意,必须在 * 前加表名作限定
SELECT * FROM employees, emp_v WHERE employees.emp_no = emp_v.emp_no
以上方法及思路均,
作者:wasrehpic
来源:https://www.nowcoder.com/questionTerminal/2435cc7b43c94d3b88ffbcfadc0241de
?intersect运算
[SQL语句 1]
INTERSECT
[SQL语句 2];
- 返回查询结果中相同的部分既他们的交集。
- INTERSECT运算自动去除重复,如果想保留所有的重复,必须用INTERSECT ALL代替INTERSECT,结果中出现的重复元组数等于两集合出现的重复元组数里较少的那个。
来源:https://www.cnblogs.com/elves/p/3653771.html
48. 将所有获取奖金的员工当前的薪水增加10%
将所有获取奖金的员工当前的薪水增加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 emp_bonus AS eb INNER JOIN salaries AS s
ON eb.emp_no = s.emp_no AND s.to_date = '9999-01-01')
知识点 | 题号 |
---|---|
修改表名 | 45 |
创建外键约束 | 46 |
交集 | 47 |
更新表 | 43,44,48 |
函数 | 44「REPLACE()」 |