牛客网SQL实战二刷 | Day8

「牛客网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的语法,其他语言的语法详见参考资料)

  1. CREATE TABLE 时的 SQL FOREIGN KEY 约束
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)
)
  1. ALTER TABLE 时的 SQL FOREIGN KEY 约束
-- 当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束,请使用下面的 SQL:

ALTER TABLE Orders
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
  1. 撤销 FOREIGN KEY 约束
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

  • 参考资料
  1. 《Sql中的并(UNION)、交(INTERSECT)、差(minus)、除去(EXCEPT)详解》https://www.cnblogs.com/elves/p/3653771.html
  2. 《SQL Intersect》 https://www.1keydata.com/cn/sql/sql-intersect.php

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`));
  • 思路
  1. 「薪水增加10%」,即更新表 salaries 中的 salary 为原来的1.1 倍;
  2. s.to_date = ‘9999-01-01’, 限定「当前薪水」。
  • 代码
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()」

你可能感兴趣的:(#,SQL学习笔记,数据分析岗秋招,面经,总结,学习资料汇总)