数据库SQL实战:MySql练习(下)

文章目录

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层(标号层)的桥梁。

猜你喜欢

转载自blog.csdn.net/sinat_34341162/article/details/83866982