文章目录
- 31. 获取select * from employees对应的执行计划
- 32. 将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分
- 33. 创建一个actor表,包含如下列信息
- 35. 对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作
- 36. 对于如下表actor,其对应的数据为:
- 37. 针对如下表actor结构创建索引:
- 38. 针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v:
- 39. 针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引
- 40. 现在在last_update后面新增加一列名字为create_date, 类型为datetime, NOT NULL,默认值为'0000 00:00:00'
- 41. 构造一个触发器audit_log,在向employees_test表中插入一条数据的时候,触发插入相关的数据到audit中
- 42. 删除emp_no重复的记录,只保留最小的id对应的记录
- 43. 将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01
- 44. 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现
- 45. 将titles_test表名修改为titles_2017
- 46. 在audit表上创建外键约束,其emp_no对应employees_test表的主键id
- 47. 存在如下的视图:
- 48. 将所有获取奖金的员工当前的薪水增加10%
- 49. 针对库中的所有表生成select count(*)对应的SQL语句
- 50. 将employees表中的所有员工的last_name和first_name通过(')连接起来。
- 51. 查找字符串'10,A,B' 中逗号','出现的次数cnt
- 52. 获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列
- 53. 按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees
- 54. 查找排除当前最大、最小salary之后的员工的平均工资avg_salary
- 55. 分页查询employees表,每5行一页,返回第2页的数据
- 56. 获取所有员工的emp_no、部门编号dept_no以及对应的bonus类型btype和recevied,没有分配具体的员工不显示
- 57. 使用含有关键字exists查找未分配具体部门的员工的所有信息
- 58. 存在如下的视图:
- 59. 获取有奖金的员工相关信息
- 60. 按照salary的累计和running_total,其中running_total为前面所有员工的salary累计和,其他以此类推。 具体结果如下Demo展示
- 61. 对于employees表,在对first_name进行排名后,选出奇数排名对应的first_name
31. 获取select * from employees对应的执行计划
- sql语句
explain select * from employees;
在 SQLite 语句之前,可以使用 “EXPLAIN” 关键字或 “EXPLAIN QUERY PLAN” 短语,用于描述表的细节。
explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。 使用方法,在select语句前加上explain就可以了。
参考:https://www.cnblogs.com/yycc/p/7338894.html
32. 将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`));
- sql语句
SELECT last_name||" "||first_name AS Name FROM employees
不同数据库连接字符串的方法不完全相同,MySQL、SQL Server、Oracle等数据库支持CONCAT方法,而本题所用的SQLite数据库只支持用连接符号"||"来连接字符串。
https://blog.csdn.net/u012260238/article/details/70245452
33. 创建一个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 | 最后更新时间,默认是系统的当前时间 |
- sql语句
create table actor(
actor_id smallint(5) primary key NOT null,
first_name varchar(45) not null,
last_name varchar(45) not null,
last_update timestamp not null default (datetime('now','localtime'))
);
使用默认值为系统时间default (datetime(‘now’,‘localtime’))
34. 对于表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
- sql语句
insert into actor values (1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'),
(2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33');
35. 对于表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'
- SQLite3
insert or ignore into actor values(3,'ED','CHASE','2006-02-15 12:34:33');
- MySQL
insert ignore into actor values(3,'ED','CHASE','2006-02-15 12:34:33');
36. 对于如下表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
(
first_name varchar(45) not null,
last_name varchar(45) not null
);
- sql语句
insert into actor_name select first_name, last_name from actor;
37. 针对如下表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。
- sql语句
create unique index uniq_idx_firstname on actor(first_name);
create index idx_lastname on actor(last_name);
给指定表或者视图的某列添加索引使用语句:
create [unique/…] index indexName on tableName(colName)
38. 针对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')))
- sql语句
create view actor_name_view as
select first_name first_name_v, last_name last_name_v
from actor;
注意 create view … as … 的 as是创建视图语法中的一部分,不可省略。
39. 针对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);
- SQLite
select * from salaries indexed by idx_emp_no where emp_no = 10005;
- MySQL
select * from salaries force index idx_emp_no where emp_no = 10005;
40. 现在在last_update后面新增加一列名字为create_date, 类型为datetime, NOT NULL,默认值为’0000 00:00:00’
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’
- sql语句
alter table actor add create_date datetime not null default '0000-00-00 00:00:00';
用alter table … add …语句可以向已存在的表插入新字段,并且能够与创建表时一样,在字段名和数据类型后加入not null、default等限定。
41. 构造一个触发器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
);
- sql语句
create trigger audit_log after insert on employees_test
begin
insert into audit values(new.id,new.name);
end;
构造触发器时注意以下几点:
1.创建触发器使用语句:create trigger triggername;
2.指定触发器触发的事件在执行某操作之前还是之后,使用语句:before/after [insert/update/add] on tablename;
3.触发器触发的事件写在begin和end之间;
4.触发器中可以通过new获得触发事件之后2对应的tablename的相关列的值,old获得触发事件之前的2对应的tablename的相关列的值。
42. 删除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');
- sql语句
delete from titles_test
where id
not in (select min(id) from titles_test group by emp_no);
本题思路如下:
先用 group by 和 min() 选出每个 emp_no 分组中最小的 id,然后用 delete from … where … not in … 语句删除 “非每个分组最小id对应的所有记录”。
43. 将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01
- sql语句
update titles_test
set to_date = NULL, from_date = '2001-01-01'
where to_date = '9999-01-01';
更新若干列:
update表名 set 列名 = 新值 where 列名 = 某值;
注意:若干列 to_date = NULL 和 from_date = ‘2001-01-01’ 之间只能用逗号连接,切勿用 and 连接。
44. 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现
- sql语句
replace into titles_test
values (5, 10005, 'Senior Engineer', '1986-06-26', '9999-01-01');
update titles_test set emp_no = replace(emp_no,10001,10005) where id = 5;
本题运用 replace有两种解法:
方法一:全字段更新替换。由于 replace的新记录中 id=5,与表中的主键 id=5 冲突,故会替换掉表中 id=5 的记录,否则会插入一条新记录(例如新插入的记录 id = 10)。并且要将所有字段的值写出,否则将置为空。
方法二:运用replace (X,Y,Z)函数。其中X是要处理的字符串,Y是X中将要被替换的字符串,Z是用来替换Y的字符串,最终返回替换后的字符串。以下语句用 update和replace配合完成,用REPLACE函数替换后的新值复制给 id=5 的 emp_no。replace的参数为整型时也可通过。
45. 将titles_test表名修改为titles_2017
- sql语句
alter table titles_test rename to titles_2017;
46. 在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
);
- sql语句
CREATE TABLE audit(
emp_no INT NOT NULL,
create_date datetime NOT NULL,
foreign key(emp_no) references employees_test(id);
);
注:SQLite中不能通过 alter table … add foreign key … references … 语句来对已创建好的字段创建外键。
SQL foreign key约束:
http://www.w3school.com.cn/sql/sql_foreignkey.asp
47. 存在如下的视图:
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 |
- sql语句
select * from emp_v;
select em.* from employees em, emp_v ev where em.emp_no = ev.emp_vo;
select * from employees intersect select * from emp_v;
方法一:利用视图的定义。emp_v的全部记录均由 employees 导出,因此直接输出 emp_v 所有记录。
方法二:用 where选取二者 emp_no 相等的记录。由于视图 emp_v 的记录是从 employees 中导出的,所以要判断两者中相等的数据,只需要判断emp_no相等即可。
方法三:用 intersect关键字求 employees 和 emp_v 的交集。
48. 将所有获取奖金的员工当前的薪水增加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`));
- sql语句
update salaries
set salary = salary * 1.1
where emp_no
in (select s.emp_no
from salaries s
join emp_bonus eb
on s.emp_no = eb.emp_no
and s.to_date = '9999-01-01');
49. 针对库中的所有表生成select count(*)对应的SQL语句
输出格式:
cnts |
---|
select count(*) from employees; |
select count(*) from departments; |
select count(*) from dept_emp; |
select count(*) from dept_manager; |
select count(*) from salaries; |
select count(*) from titles; |
- sql语句
select "select count(*) from " || name || ";" cnts
from sqlite_master
where type = 'table';
本题主要有以下两个关键点:
1、SQLite数据库中一个特殊的名叫 sqlite_master 上执行一个select查询以获得所有表的索引。每一个 SQLite 数据库都有一个叫sqlite_master的表, 它定义数据库的模式。
对于表来说,type 字段永远是 ‘table’,name 字段永远是表的名字。
2、在 SQLite 中用 “||” 符号连接字符串。
50. 将employees表中的所有员工的last_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`));
输出格式:
name |
---|
Facello’Georgi |
Simmel’Bezalel |
Bamford’Parto |
Koblick’Chirstian |
Maliniak’Kyoichi |
Preusig’Anneke |
- sql语句
select last_name || "'" || first_name name
from employees;
51. 查找字符串’10,A,B’ 中逗号’,'出现的次数cnt
- sql语句
select (length("10,A,B")-length(replace("10,A,B",",","")))/length(",") cnt
使用length()函数与replace()函数的结合灵活地解决了统计子串出现次数的问题,属于技巧题,即先用replace函数将原串中出现的子串用空串替换,再用原串长度减去替换后字符串的长度,最后除以子串的长度(本题中此步可省略,若子串长度大于1则不可省)。
52. 获取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 |
- sql语句
select first_name
from employees
order by substr(first_name,length(first_name)-1);
本题考查 substr(X,Y,Z) 或 substr(X,Y) 函数的使用。其中X是要截取的字符串。Y是字符串的起始位置(注意第一个字符的位置为1,而不为0),取值范围是±(1~length(X)),当Y等于length(X)时,则截取最后一个字符;当Y等于负整数-n时,则从倒数第n个字符处截取。Z是要截取字符串的长度,取值范围是正整数,若Z省略,则从Y处一直截取到字符串末尾;若Z大于剩下的字符串长度,也是截取到字符串末尾为止。
53. 按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果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`));
输出格式:
dept_no | employees |
---|---|
d001 | 10001,10002 |
d002 | 10006 |
d003 | |
d004 | 10003,10004 |
d005 | 10007,10008,10010 |
- SQLite
select dept_no, group_concat(emp_no) employees
from dept_emp
group by dept_no;
- MySQL
select dept_no,group_concat(emp_no SEPARATOR ',') employees
from dept_emp
group by dept_no;
本题要用到SQLite的聚合函数group_concat(X,Y),其中X是要连接的字段,Y是连接时用的符号,可省略,默认为逗号。此函数必须与 GROUP BY 配合使用。
54. 查找排除当前最大、最小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 |
- sql语句
select avg(salary) 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);
55. 分页查询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`));
- sql语句
select *
from employees
limit 5,5;
在 limit X,Y 中,Y代表返回几条记录,X代表从第几条记录开始返回(第一条记录序号为0),切勿记反。
56. 获取所有员工的emp_no、部门编号dept_no以及对应的bonus类型btype和recevied,没有分配具体的员工不显示
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`));
输出格式:
e.emp_no | dept_no btype | recevied |
---|---|---|
10001 | d001 | 1 |
10002 | d001 | 2 |
10003 | d004 | 3 |
10004 | d004 | 1 |
10005 | d003 | |
10006 | d002 | |
10007 | d005 | |
10008 | d005 | |
10009 | d006 | |
10010 | d005 |
- sql语句
select e.emp_no,de.dept_no,eb.btype,eb.recevied
from employees e
join dept_emp de on e.emp_no = de.emp_no
left join emp_bonus eb on e.emp_no = eb.emp_no;
本题严谨的思路为,先将 employees与dept_emp 用 join 连接,挑选出分配了部门的员工,再用left join连接 emp_bonus(在前面的题中可看到此表),分配了奖金的员工显示奖金类型和授予时间,没分配奖金的员工则不显示。
57. 使用含有关键字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 |
---|
- sql语句
select *
from employees
where not exists
(select emp_no from dept_emp where emp_no = employees.emp_no);
select *
from employees
where emp_no not in (select emp_no from dept_emp);
58. 存在如下的视图:
create view emp_v as select * from employees where emp_no >10005;
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`));
获取employees中的行数据,且这些行也存在于emp_v中。注意不能使用intersect关键字。
输出格式:
emp_no | birth_date | first_name | last_name | gender | hire_date |
---|---|---|---|---|---|
10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 |
- sql语句
select * from emp_v;
select em.* from employees em, emp_v ev where em.emp_no = ev.emp_vo;
59. 获取有奖金的员工相关信息
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 |
- sql语句
select e.emp_no, e.first_name first_name, e.last_name last_name, b.btype btype, s.salary salary,
(case b.btype
when 1 then s.salary * 0.1
when 2 then s.salary * 0.2
else s.salary * 0.3 end) bonus
from employees e
join emp_bonus b
on e.emp_no = b.emp_no
join salaries s
on e.emp_no = s.emp_no
and s.to_date = '9999-01-01';
本题主要考查 SQLite 中 CASE 表达式的用法。即当 btype = 1 时,得到 salary * 0.1;当 btype = 2 时,得到 salary * 0.2;其他情况得到 salary * 0.3。
条件表达式:
CASE x WHEN w1 THEN r1 WHEN w2 THEN r2 ELSE r3 END
60. 按照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 |
- sq语句
select s1.emp_no, s1.salary,
(select sum(s2.salary)
from salaries s2
where s2.emp_no <= s1.emp_no
and s2.to_date = '9999-01-01') running_total
from salaries s1
where s1.to_date = '9999-01-01'
order by s1.emp_no;
本题的思路为复用 salaries 表进行子查询,最后以 s1.emp_no 排序输出求和结果。
1、输出的第三个字段,是由一个 select子查询构成。将子查询内复用的 salaries 表记为 s2,主查询的 salaries 表记为 s1,当主查询的 s1.emp_no 确定时,对子查询中不大于 s1.emp_no 的 s2.emp_no 所对应的薪水求和。
2、注意是对员工当前的薪水求和,所以在主查询和子查询内都要加限定条件 to_date = ‘9999-01-01’。
61. 对于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 |
---|
Georgi |
Chirstian |
Anneke |
Tzvetan |
Saniya |
- sql语句
select e1.first_name from
(select e2.first_name,
(select COUNT(*) from employees e3
where e3.first_name <= e2.first_name) rowid
from employees e2) e1
where e1.rowid % 2 = 1;
本题思路:
1、用到了三层 select查询,为了便于理解,采用缩进方式分层,且最外层对应e1,最内层对应e3;
2、在e3层中,采用 count() 函数对 e2.first_name 进行排名标号,即在给定 e2.first_name的情况下,不大于 e2.first_name 的 e3.first_name 的个数有多少,该个数刚好与 e2.first_name 的排名标号匹配,且将该值命名为 rowid;
/注意:排名标号后并未排序,即[Bob, Carter, Amy]的排名是[2,3,1],选取奇数排名后输出[Carter, Amy],所以可见参考答案中的first_name并未按字母大小排序/
3、在e1层中,直接在限定条件 e1.rowid % 2 = 1 下,代表奇数行的 rowid,选取对应的 e1.first_name;
4、e2层则相当于连接e1层(选取表示层)与e3层(标号层)的桥梁。