牛客网的测试系统是SQLite,所以有一些用法与MySQL不一致
select * from employees order by hire_date desc limit 0,1
方法1:若最晚入职员工只有1人,则按入职时间倒序排列,排在第一的就是目标人员。
select * from employees
where hire_date=(select max(hire_date) from employees)
方法2:若最晚入职员工不止1人,则先查出最晚的入职日期,再用此日期作为筛选条件。
select * from employees order by hire_date desc limit 2,1
此题考查order by和limit用法:
感觉题目有点问题:增加一句“输出结果按emp_no递增排序”就没异议了。
题干中的“输出描述”已经暗含了此排序,输出结果必须与之完全一致才能通过(这确实有些不合理)。
解法1:salaries作为主表,salaries的主键是emp_no,结果按emp_no递增排序
select s.* ,d.dept_no from salaries as s
join dept_manager as d on s.emp_no=d.emp_no
where s.to_date = '9999-01-01'
and d.to_date='9999-01-01'
解法2:dept_manager作为主表,dept_manager的主键是dept_no,结果按dept_no递增排序
select s.* ,d.dept_no from salaries as s
inner join dept_manager as d on s.emp_no=d.emp_no
where s.to_date = '9999-01-01'
and d.to_date='9999-01-01'
order by s.emp_no #比解法1多了一步按emp_no递增排序
select e.last_name,e.first_name,d.dept_no
from dept_emp as d
join employees as e on d.emp_no=e.emp_no
where dept_no is not null;
select e.last_name,e.first_name,d.dept_no
from employees as e
left join dept_emp as d on e.emp_no=d.emp_no
select e.emp_no,s.salary
from employees as e
left join salaries as s
on e.emp_no=s.emp_no
and e.hire_date=s.from_date
order by e.emp_no desc
select emp_no,count(emp_no) as t
from salaries group by emp_no having t > 15
虽然本题通过了,但严格来讲不够严谨。本题每出现一次工资就认为涨幅1次,但可能不变,也可能降薪。
select distinct salary from salaries
where to_date='9999-01-01'
group by emp_no
order by salary desc
select d.dept_no,s.emp_no,s.salary
from salaries as s
left join dept_manager as d
on s.emp_no=d.emp_no
where d.to_date='9999-01-01'
and s.to_date='9999-01-01'
同题目3
select emp_no from employees
where emp_no not in
(
select emp_no from dept_manager
)
select de.emp_no,dm.emp_no as manager_no
from dept_emp as de
left join dept_manager as dm
on de.dept_no=dm.dept_no
and dm.to_date='9999-01-01'
where de.emp_no <> dm.emp_no
select d.dept_no,d.emp_no,max(salary)
from dept_emp as d
left join salaries as s
on d.emp_no=s.emp_no
where d.to_date='9999-01-01'
group by d.dept_no
select title,count(*) as t from titles
group by title
having t>=2
解法1:
select title,count(1) as t from
(select distinct emp_no,title from titles)
group by title
having t>=2
解法2:
select title,count(distinct emp_no) as t from titles
group by title
having t>=2
select * from employees
where emp_no % 2 = 1
and last_name <> "Mary"
order by hire_date desc
延展思考:判断奇数偶数常用办法
1.位运算:位运算符是在二进制数上进行计算的运算符。位运算会先将操作数变成二进制数,进行位运算。然后再将计算结果从二进制数变回十进制数。
- 按位与
位运算是对数的二进制进行的运算,利用按位与操作,就是 & 。奇数的二进制数的最后一位永远是 1,与 1 按位且只会得到 1,偶数相反。select * from table where id&1 #筛选奇数
- 右移1和左移1
右移1(>>1)相当于十进制除以2,左移1(<<1)相当于十进制乘以2,先乘2再除2,若与原数相等则是偶数,不等是奇数。select * from table where id<>(id>>1)<<1 #筛选奇数 select * from table where id=(id>>1)<<1 #筛选偶数
2. id计算
- 求余数:%2或MOD(id,2),除以2余数是1则为奇数,余数是0则为偶数
select * from table where id%2=1 #筛选奇数 select * from table where id%2=0 #筛选偶数
select * from table where mod(id,2)=1 #筛选奇数 select * from table where mod(id,2)=0 #筛选偶数
- -1的奇数次方和偶数次方
select * from table where power(-1,id)=-1 #筛选奇数 select * from table where power(-1,id)=1 #筛选偶数
select title,avg(salary) from salaries
left join titles on salaries.emp_no=titles.emp_no
where salaries.to_date='9999-01-01'
and titles.to_date='9999-01-01'
group by title
select emp_no,salary from salaries
where to_date='9999-01-01'
order by salary desc
limit 1,1
select e.emp_no,s.salary,e.last_name,e.first_name
from employees as e
left join salaries as s
on e.emp_no=s.emp_no
where to_date='9999-01-01'
and s.emp_no =
(
select emp_no from salaries
where salary=
(
select max(salary) from salaries where salary<
(
select max(salary) from salaries
)
)
)
select e.last_name,e.first_name,d.dept_name
from employees as e
left join dept_emp as de
on e.emp_no=de.emp_no
left join departments as d
on de.dept_no=d.dept_no
select max(salary)-min(salary) as growth from salaries where emp_no=10001
select a.top - b.down as growth
from (select emp_no,max(to_date),salary as top from salaries where emp_no=10001) as a
join (select emp_no,min(to_date),salary as down from salaries where emp_no=10001) as b
on a.emp_no=b.emp_no
select
s1.salary-s2.salary as growth
from
(select emp_no,salary from salaries where emp_no=10001 order by salary desc limit 1) as s1
join
(select emp_no,salary from salaries where emp_no=10001 order by salary asc limit 1) as s2
on
s1.emp_no=s2.emp_no
select e.emp_no,s1.salary-s2.salary as growth
from employees as e
inner join salaries as s1
on s1.emp_no=e.emp_no and s1.to_date ='9999-01-01'
inner join salaries as s2
on s2.emp_no=e.emp_no and s2.from_date=e.hire_date
order by growth asc
select d.dept_no,d.dept_name,count(1) as sum
from departments as d
left join dept_emp as de
on d.dept_no=de.dept_no
left join salaries as s
on de.emp_no=s.emp_no
group by d.dept_no
dept_no
emp_no
,dept_no
emp_no
,from_date
select s1.emp_no,s1.salary,count(distinct s2.salary) as rank
from salaries as s1,salaries as s2
where s1.to_date='9999-01-01' and s2.to_date='9999-01-01' and s1.salary<=s2.salary
group by s1.emp_no
order by rank asc,s1.emp_no asc
select de.dept_no,de.emp_no,salary
from dept_emp as de,employees as e,salaries as s
where de.emp_no not in(select emp_no from dept_manager)
and de.emp_no=e.emp_no
and de.emp_no=s.emp_no
and s.to_date='9999-01-01'
select
emp.emp_no as emp_no,manager.emp_no as manager_no,
emp.salary as emp_salary,
manager.salary as manager_salary
from
(select de.emp_no,de.dept_no,salary from dept_emp as de,salaries
where de.emp_no=salaries.emp_no
and salaries.to_date='9999-01-01') as emp
inner join
(select dm.emp_no,dm.dept_no,salary from dept_manager as dm,salaries
where dm.emp_no=salaries.emp_no
and salaries.to_date='9999-01-01') as manager
on
emp.dept_no=manager.dept_no and emp.salary>manager.salary
select d.dept_no,d.dept_name,t.title,count(t.title)
from titles as t
inner join dept_emp as de on de.emp_no=t.emp_no
inner join departments as d on d.dept_no=de.dept_no
where t.to_date='9999-01-01' and de.to_date='9999-01-01'
group by d.dept_no,t.title
select s1.emp_no,s2.from_date,s2.salary-s1.salary as salary_growth
from salaries as s1,salaries as s2
where s1.emp_no=s2.emp_no
and salary_growth>5000
and (strftime('%Y',s2.to_date)-strftime('%Y',s1.to_date)=1
or strftime('%Y',s2.from_date)-strftime('%Y',s1.from_date)=1)
order by salary_growth desc
假设s1是涨薪水前的表,s2是涨薪水后的表,因为每个员工涨薪水的时间不全固定,有可能一年涨两次,有可能两年涨一次,所以每年薪水的涨幅,应该理解为两条薪水记录的from_date相同或to_date相同。“每年”,strftime(’%Y’,s2.to_date)-strftime(’%Y’,s1.to_date)=1
select c.name,count(c.name)
from (select category_id
from film_category
group by category_id
having count(film_id)>=5) as ca,
film as f,category as c,film_category as fc
where f.film_id=fc.film_id
and c.category_id=fc.category_id
and fc.category_id=ca.category_id
and f.description like "%robot%"
建立虚拟表,将电影数量>=5的分类找出来,再连接其他表
以下是典型错误的:因为f.description like "%robot%"过滤后,电影分类下所属的电影数量减少了,之后再分组并count>=5,得不出正确结果
select c.name,count(c.name)
from film as f,category as c,film_category as fc
where f.film_id=fc.film_id
and c.category_id=fc.category_id
and f.description like "%robot%"#过滤后,电影分类下所属的电影数量减少了
group by c.name
having count(c.name)>=5
select f.film_id,f.title from film as f
left join film_category as fc on f.film_id=fc.film_id
left join category as c on c.category_id=fc.category_id
where c.category_id is null
#一般形式:
select ID,name from Table_A where ID not in (select ID from Table_B)
#替代方案:
select ID,name from Table_A left join Table_B on Table_A.id=Table_B.id where Table_B.id is null
注意:不要在on时判断为空,会与预期不同,需在where时判断
select title,description from film where film_id in
(
select film_id from film_category where category_id in
(
select category_id from category where name = "Action"
)
)
explain select * from employees
MySQL、SQL Server、Oracle等数据库支持CONCAT方法,
而本题所用的SQLite数据库只支持用连接符号"||"来连接字符串
CONCAT方法:
select CONCAT(CONCAT(last_name," "),first_name) as name from employees
或者
select CONCAT(last_name," ",first_name) as name from employees
本题中使用:
select last_name||" "||first_name as name from employees
列表 | 类型 | 是否为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 if not exists actor(
actor_id smallint(5) not null,
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)
);
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(actor_id,first_name,last_name,last_update)
values
(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');
insert into actor values(2,'NICK','WAHLBERG','2006-02-15 12:34:33');
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')
#若不存在,则插入;若存在,则代替
insert or replace into actor values('3','ED','CHASE','2006-02-15 12:34:33')
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 if not exists actor_name as
select first_name,last_name from actor;
create table if not exists actor_name
(
first_name varchar(45) not null,
last_name varchar(45) not null
);
insert into actor_name
select first_name,last_name from actor;
create unique index uniq_idx_firstname on actor(first_name);
create index idx_lastname on actor(last_name);
alter table actor add unique index uniq_idx_first(first_name);
alter table actor add index idx_lastname(last_name);
create view actor_name_view as
select first_name as first_name_v,last_name as last_name_v from actor
select * from salaries indexed by idx_emp_no where emp_no=10005;
select * from salaries force index(idx_emp_no) where emp_no=10005;
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:00:00’
alter table actor add create_date datetime not null default '0000-00-00 00:00:00'
alter table actor add create_date after last_update datetime not null default '0000-00-00 00:00:00'
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 if not exists audit_log
after insert on employees_test for each row
begin
insert into audit values(new.id,new.name);
end;
MYSQL触发器详细用法参考:MySQL 触发器学习教程
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 table_name where 条件
delete from titles_test where id in
(select max(id) from titles_test group by emp_no having count(1)>1);
delete from titles_test where id not in
(select min(id) from titles_test group by emp_no);
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);
update titles_test set to_date=NULL,from_date='2001-01-01'
where to_date='9999-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);
update titles_test set emp_no=replace(emp_no,10001,10005)
where id=5 and emp_no=10001;
replace用法如下
mysql中replace函数直接替换mysql数据库中某字段中的特定字符串,不再需要自己写函数去替换,用起来非常的方便
Update table_name
SET field_name
= replace (field_name
,’from_str’,'to_str’) Where field_name
LIKE ‘%from_str%’
说明:
table_name —— 表的名字
field_name —— 字段名
from_str —— 需要替换的字符串
to_str —— 替换成的字符串
alter table titles_test rename to titles_2017;
修改表名:ALTER TABLE 旧表名 RENAME TO 新表名
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,能通过的版本
DROP TABLE audit;
CREATE TABLE audit(
EMP_no INT NOT NULL,
create_date datetime NOT NULL,
FOREIGN KEY(EMP_no) REFERENCES employees_test(ID));
#mysql版本
alter table audit add foreign key(emp_no) references employees_test(id);
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
));
分析:把视图就当做表,求两个表的交集
解法1:join
select em.* from employees as em
join emp_v
using(emp_no)#using(emp_no)等价于on em.emp_no=emp_v.emp_no
解法2:from多表,where限定
select em.* from employees as em,emp_v
where em.emp_no=emp_v.emp_no
注:from多表和join多表效果和效率是一样的
解法3:emp_v本身就是employees的子集,所以直接输出emp_v即可
select * from emp_v
错误解法:没对*做限定,结果会将2表左右合并全部输出
select * from employees as em
join emp_v
using(emp_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
));
update salaries set salary=1.1 *salary where emp_no in
(select emp_no from emp_bonus)
MySQL的方法,牛客网不能通过
select concat("select count(*) from "," ",table_name,";") as counts from (select table_name from information_schema.tables
where table_schema='mydata') as new;
MySQL语句中,‘mydata’是当前数据库的名称
information_schema.tables表示从表名中选择,information_schema.xxx中xxx可选的还有很多字段,如information_schema.columns表示从所有表的所有字段中选择。
MySQL字符串的连接使用concat函数,则按照要求可以有以下代码:
select concat(“select count(*) from “,table_name,”;”) as countts
from information_schema.tables where table_schema=‘mydata’;
参考文章:mysql数据库所有的表生成select count(*) 对应的sql语句
MySQL的方法,牛客网不能通过
select concat(last_name,"'",first_name) as name from employees
select (length('10,A,B')-length(replace('10,A,B',',','')))/length(',') as cnt
MySQL答案
select first_name from employees
order by right(first_name,2) asc
SQLite牛客网答案
方法1:
select first_name from employees
order by substr(first_name,length(first_name)-1,2) asc
方法2
select first_name from employees
order by substr(first_name,-2)
substr(字符串,起始位置,[截取长度]),若起始位置是正数,则从左往右数,第一位是1不是0;若起始位置是负数,则从右往左数;截取长度可选,不写时截取到最后。
此题的启示:order by 语句中也可使用函数
其他的Mysql字符串截取总结:left()、right()、substring()、substring_index()
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
));
牛客网SQLite解法
select dept_no,group_concat(emp_no) as employees
from dept_emp group by dept_no
MySQL解法
select dept_no,group_concat(emp_no) as employees
from dept_emp group by dept_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
));
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)
上述结果尽管能通过,但与原题目对不上,
要么调整题目:
查找排除最大、最小salary之后的当前员工的平均工资avg_salary
要么应该这样写:
select avg(salary) as avg_salary from salaries
where to_date = '9999-01-01'
and salary not in (select max(salary) from salaries where to_date = '9999-01-01')
and salary not in (select min(salary) from salaries where to_date = '9999-01-01')
select avg(salary) as avg_salary from salaries
where salary not in(select min(salary),max(salary) from salaries)
and to_date = '9999-01-01';
错误原因:select min(salary),max(salary) from salaries是两列值,所以salary not in两列结果为错
select * from employees limit (2-1)*5,5
limit用法:
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);
select e.emp_no,de.dept_no,eb.btype,eb.recevied
from employees as e
inner join dept_emp as de on e.emp_no=de.emp_no
left join emp_bonus as eb on eb.emp_no=de.emp_no
ps.原题创建表时有个拼写错误,received错拼成recevied,所以必须错着写才能有数据
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
));
select * from employees
where not exists (select emp_no from dept_emp where emp_no=employees.emp_no)
使用in的方法
select * from employees
where emp_no not in (select emp_no from dept_emp)
什么时候用in,什么时候用exists?
通常情况下采用exists要比in效率高,因为IN不走索引,但要看实际情况具体使用:
- 外表大内表小用in,外表小内表大用exists,内外表大小差不多,用谁都行
- 与not连用时,只用not exists,要比not in效率高
存在如下的视图:
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
));
select * from emp_v
视图跟表一样使用。emp_v是employees的子集,所以直接输出emp_v的全部数据即满足题意
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 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’
select e.emp_no,e.first_name,e.last_name,b.btype,s.salary,
(
case btype
when 1 then s.salary * 0.1
when 2 then s.salary * 0.2
else s.salary * 0.3
end) as bonus
from employees as e
join emp_bonus as b on e.emp_no=b.emp_no
join salaries as s on e.emp_no=s.emp_no and s.to_date='9999-01-01'
case when 用法:
case colomn
when condition1 then result1
when condition2 then result2
when condition3 then result3
else result4
end
注意最后要有end
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:子查询,单表自引用
select s1.emp_no,s1.salary,
(select sum(s2.salary) from salaries as s2
where s2.emp_no<=s1.emp_no and s2.to_date='9999-01-01')as running_total
from salaries as s1
where s1.to_date='9999-01-01'
order by s1.emp_no asc
解法2: 定义函数自增量
select emp_no,salary,@total:= @total + salary as running_total
from salaries,(select @total:=0) a
where to_date='9999-01-01'
order by emp_no asc
解法3:窗口函数(mysql8.0及以上版本可用)
select emp_no,salary,sum(salary)over(order by emp_no) as running_total from salaries
where to_date='9999-01-01'
聚合函数sum作为窗口函数的使用方法:
sum(求和列)over([partition by 分区列]order by 排序列 asc/desc)
分区列和排序列可以不在select列表中,但必须在数据源中,order by只对所在分区中的数据进行排序,与select语句中的排序无关,[partition by 分区列]可省略,若未省略则表示分组累计求和。
解法1:定义函数自增量
select a.first_name
from (select @row: = @row + 1 as rownum, e.first_name from employees as e,(select @row: = 0 ) b ) a
where a.rownum % 2 = 1
解法2:子查询
select e1.first_name
from employees as e1
where (select count(*) from employees as e2 where e1.first_name<=e2.first_name)%2=1