1 查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth
select(
(select salary from salaries where emp_no=10001 order by to_date desc limit 1)-
(select salary from salaries where emp_no=10001 order by to_date asc limit 1)
)
as growth
2
汇总各个部门当前员工的title类型的分配数目,结果给出部门编号dept_no、dept_name、其当前员工所有的title以及该类型title对应的数目count
select de.dept_no,d.dept_name,t.title,count (t.title) as count
from departments d inner join dept_emp de on d.dept_no = de.dept_no
and de.to_date='9999-01-01'
inner join titles t on t. emp_no =de.emp_no
and t.to_date='9999-01-01'
group by de.dept_no,t.title
3 给出每个员工每年薪水涨幅超过5000的员工编号emp_no、薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列。
提示:在sqlite中获取datetime时间对应的年份函数为strftime(‘%Y’, to_date)
select s1.emp_no,s1.from_date,(s1.salary-s2.salary) as salary_growth
from salaries s1,salaries s2
where (strftime('%Y',s1.to_date)-strftime('%Y',s2.to_date))=1
and salary_growth>5000
and s1.emp_no=s2.emp_no ######重要
order by salary_growth desc
4 使用含有关键字exists查找未分配具体部门的员工的所有信息。
select *
from employees e
where not exists (select emp_no from dept_emp d where e.emp_no = d.emp_no)
5 对于employees表中,给出奇数行的first_name
select e1.first_name
from employees e1
where (select count(*) from employees e2 where e1.first_name<=e2.first_name) %2=1
6 针对库中的所有表生成select count(*)对应的SQL语句
select "select count(*) from "||name||";" as cnts
from sqlite_master where type='table'
7 将所有获取奖金的员工当前的薪水增加10%。
update salaries set salary =salary*1.1
where emp_no in (select s.emp_no from salaries s ,emp_bonus eb
where eb.emp_no =s.emp_no
and s.to_date='9999-01-01')
8 在audit表上创建外键约束,其emp_no对应employees_test表的主键id。
实际mysql使用ALTER添加外键的语句表达式为:ALTER TABLE tablename 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));
9 将titles_test表名修改为titles_2017。
alter table titles_test rename to titles_2017
10 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。
本题运用 REPLACE 有两种解法
方法一:全字段更新替换。由于 REPLACE 的新记录中 id=5,与表中的主键 id=5 冲突,故会替换掉表中 id=5 的记录,否则会插入一条新记录(例如新插入的记录 id = 10)。并且要将所有字段的值写出,否则将置为空。
replace into titles_test values ('5','10005','Senior Engineer','1986-06-26','9999-01-01')
方法二:运用REPLACE(X,Y,Z)函数。其中X是要处理的字符串,Y是X中将要被替换的字符串,Z是用来替换Y的字符串,最终返回替换后的字符串。以下语句用 UPDATE和REPLACE 配合完成,用REPLACE函数替换后的新值复制给 id=5 的 emp_no。REPLACE的参数为整型时也可通过。
update titles_test set emp_no=replace(emp_no,10001,10005)where id =5
/** 另外可以利用OJ系统的漏洞,不用 REPLACE 实现 **/
UPDATE titles_test SET emp_no = 10005 WHERE id = 5
11 将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。
update titles_test set to_date=Null ,from_date='2001-01-01'
where to_date='9999-01-01'
12 删除emp_no重复的记录,只保留最小的id对应的记录。
delete from titles_test where id
not in (select min(id) from titles_test group by emp_no)
13
1.创建触发器使用语句:CREATE TRIGGER trigname;
2.指定触发器触发的事件在执行某操作之前还是之后,使用语句:BEFORE/AFTER [INSERT/UPDATE/ADD] ON tablename
3.触发器触发的事件写在BEGIN和END之间;
4.触发器中可以通过NEW获得触发事件之后2对应的tablename的相关列的值,OLD获得触发事件之前的2对应的tablename的相关列的值
create trigger audit_log after insert on employees_test
begin
insert into audit values (new.id,new.name);
end;
14 actor表中在last_update后面新增加一列名字为create_date, 类型为datetime, NOT NULL,默认值为'0000 00:00:00'
用 ALTER TABLE ... ADD ... 语句可以向已存在的表插入新字段,并且能够与创建表时一样,在字段名和数据类型后加入NOT NULL、DEFAULT等限定。
alter table actor
add column 'create_date' datetime not null default '0000-00-00 00:00:00';
其中 ADD 后的 COLUMN 可省略,NOT NULL 和 DEFAULT '0000-00-00 00:00:00' 可交换:
ALTER TABLE actor ADD create_date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL ;
在mysql中可以使用after.
15 SQLite中,使用 INDEXED BY 语句进行强制索引查询
select * from salaries indexed by idx_emp_no where emp_no=10005
MySQL中,使用 FORCE INDEX 语句进行强制索引查询
SELECT * FROM salaries FORCE INDEX idx_emp_no WHERE emp_no = 10005
16 针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v:
本题可用以下两种方法求解,区别在于命名VIEW中字段名的方法差异。另外,本题OJ系统有Bug,由错误提示可以看到,VIEW中本应有字段first_name_v,而OJ系统误设为了fist_name_v。
方法一:注意 CREATE VIEW ... AS ... 的 AS 是创建视图语法中的一部分,而后面的两个 AS 只是为字段创建别名
create view actor_name_view as
select first_name as first_name_v,last_name as last_name_v
from actor
方法二:直接在视图名的后面用小括号创建视图中的字段名
create view actor_name_view (first_name_v,last_name_v) as
select first_name ,last_name
from actor
17 根据题意,本题要用两条语句完成,先用 CREATE UNIQUE INDEX ... ON ... 对first_name创建唯一索引值,再用 CREATE INDEX ... ON ... 对last_name创建普通索引值
create unique index uniq_idx_firstname on actor(first_name);
create index idx_lastname on actor(last_name);
18 创建一个actor_name表,将actor表中的所有first_name以及last_name导入改表。 actor_name表结构如下:
根据题意,本题要用两条语句完成,先用 CREATE TABLE 语句创建actor_name表,包含first_name与last_name字段,然后用 INSERT INTO ... SELECT ... 语句向actor_name表插入另一张表中的数据
create table actor_name(
first_name varchar(45) not null,
last_name varcher(45) not null
);
insert into actor_name select first_name,last_name from actor
19 对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作
在 SQLite 中,用 INSERT OR IGNORE 来插入记录,或忽略插入与表内UNIQUE字段都相同的记录
insert or ignore into actor
values('3','ED','CHASE','2006-02-15 12:34:33')
用 INSERT OR REPLACE 来插入记录,或更新替代与表内UNIQUE字段都相同的记录
insert or replace into actor
values('3','ED','CHASE','2006-02-15 12:34:33')
#######################################
因为题目判定系统使用的是sqlite3,所以必须按sqlite3的写法来做,
insert or ignore into actor
values(3,'ED','CHASE','2006-02-15 12:34:33');
如果是mysql,那么把or去掉,像下面这样:
insert IGNORE into actor
values(3,'ED','CHASE','2006-02-15 12:34:33');
两种数据库还是有区别的。
20 对于表actor批量插入如下数据
本题的批量插入数据要求在一条语句内完成,以下有两种方法供参考:
方法一:利用VALUES(value1, value2, ...), (value1, value2, ...), ...(value1, value2, ...),
insert into actor
values(1,"PENELOPE","GUINESS",'2006-02-15 12:34:33'),
(2,"NICK","WAHLBERG",'2006-02-15 12:34:33');
方法二:利用 UNION SELECT 批量插入
insert into actor
select 1,"PENELOPE","GUINESS",'2006-02-15 12:34:33'
union select 2,"NICK","WAHLBERG",'2006-02-15 12:34:33'
21 创建一个actor表,包含如下列信息
create table 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'))
)
//primary key(actor_id)
//最后一句不加逗号
22 题目描述
将employees表中的所有员工的last_name和first_name通过(')连接起来。
在本题所用的SQLite数据库中,只支持用连接符号"||"来连接字符串,不支持用函数连接
SELECT last_name || "'" || first_name FROM employees
空格链接的话 || “ ” ||
23 获取select * from employees对应的执行计划
在SQLite数据库中,可以用 "EXPLAIN" 关键字或 "EXPLAIN QUERY PLAN" 短语,用于描述表的细节。
explain select * from employees
24 使用子查询的方式找出属于Action分类的所有电影对应的title,description
//子查询
select f.title,f.description
from film f
where f.film_id in (select fc.film_id from film_category fc
where fc.category_id in (select c.name="Action" from category c ))
//非子查询
select f.title,f.description
from film f inner join film_category fc on f.film_id=fc.film_id
inner join category c on fc.category_id=c.category_id
where c.name='Action'
25 使用join查询方式找出没有分类的电影id以及名称
解题思路是运用 LEFT JOIN 连接两表,用 IS NULL 语句限定条件:
1、用 LEFT JOIN 连接 film 和 film_category,限定条件为 f.film_id = fc.film_id,即连接电影 id 和电影分类 id,如果电影没有分类,则电影分类 id 显示 null
2、再用 WHERE 来限定条件 fc.category_id IS NULL 选出没分类的电影
/* 注意:最后一句若写成 ON f.film_id = fc.film_id AND fc.category_id IS NULL,则意义变成左连接两表 film_id 相同的记录,且 film_category 原表中的 fc.category 的值为 null。显然,原表中的 fc.category 的值恒不为 null,因此(f.film_id = fc.film_id AND fc.category_id IS NULL)恒为 FALSE,左连接后则只会显示 film 表的数据,而 film_category 表的数据全显示为 null */
select f.film_id,f.title
from film f left join film_category fc
on f.film_id=fc.film_id
where fc.category_id is Null
26 查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部
1、找到对应电影数量>=5的所有分类,建立成虚表cc:(select category_id, count(film_id) as category_num from film_category group by category_id having count(film_id)>=5) as cc
2、设定限制条件 f.description like '%robot%'
3、在表cc、f、fc、c中查找包括robot的电影对应的分类名称和对应的电影数目。
select c.name,count(fc.film_id) from
(select category_id ,count(film_id )
from film_category group by category_id
having count(film_id)>=5
) as cc ,film f,film_category fc,category c
where f.film_id=fc.film_id
and c.category_id=fc.category_id
and c.category_id = cc.category_id
and f.description like '%robot%'