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');
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%'