SQL练习(牛客网)

查找入职员工时间排名倒数第三的员工所有信息

select * from employees 
order by hire_date desc limit 2,1
#desc表示降序,从高到低,即时间最晚的最高,在最前面
#检索从第2行开始向前检索1条数据

查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no

select salaries.emp_no,salaries.salary,salaries.from_date,salaries.to_date,dept_manager.dept_no
#各变量名之前指明来自何表
from salaries inner join dept_manager
#结果中salaries在前,dept-no在后,则salaries为主表,顺序不可错
on(dept_manager.emp_no=salaries.emp_no)
where dept_manager.to_date='9999-01-01' and salaries.to_date='9999-01-01'
#条件查询,同时对两个表都要声明

查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工

select last_name,first_name,dept_no 
from employees left join dept_emp
#INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示。
#LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
#RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据。
on(employees.emp_no=dept_emp.emp_no)

查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序

select a.emp_no,b.salary
from employees a 
inner join salaries b
#emp_no在前,主表为employees
#表别名可不加AS
on a.emp_no=b.emp_no and a.hire_date=b.from_date
order by a.emp_no desc

查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t

select emp_no,count(emp_no) as t 
from salaries 
group by emp_no 
HAVING t > 15

获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。
结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。

select a.emp_no,b.emp_no as manager_no
from dept_emp a inner join dept_manager b
on a.dept_no=b.dept_no
where a.to_date='9999-01-01' and b.to_date='9999-01-01' and a.emp_no<>b.emp_no

获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary

select a.dept_no,b.emp_no,max(b.salary) as salary
from dept_emp a join salaries b
on a.emp_no=b.emp_no
where a.to_date = '9999-01-01' and b.to_date = '9999-01-01'
group by a.dept_no
或者
select a.dept_no,b.emp_no,b.salary
from dept_emp a join salaries b
on a.emp_no=b.emp_no
where a.to_date = '9999-01-01' and b.to_date = '9999-01-01'
group by a.dept_no
having b.salary =max(b.salary)

从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t

select title,count(title) as t
from titles
group by title
having t>=2

查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列

select emp_no,birth_date,first_name,last_name,gender,hire_date
from employees
where emp_no%2<>0 and last_name<>"Mary"
order by hire_date desc

统计出当前各个title类型对应的员工当前薪水对应的平均工资。结果给出title以及平均工资avg

select b.title,avg(a.salary) as avg
from titles b left join salaries a
on b.emp_no=a.emp_no
where b.to_date = '9999-01-01' AND a.to_date = '9999-01-01'
group by b.title

获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary

select emp_no,salary
from salaries
where to_date='9999-01-01' 
order by salary desc limit 1,1

查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by

select a.emp_no,max(b.salary),a.last_name,a.first_name
from employees a inner join salaries b
on a.emp_no=b.emp_no
where to_date='9999-01-01' and salary not in (select max(salary) from salaries)

查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工

运用两次LEFT JOIN连接嵌套
1、第一次LEFT JOIN连接employees表与dept_emp表,得到所有员工的last_name和first_name以及对应的dept_no,也包括暂时没有分配部门的员工
2、第二次LEFT JOIN连接上表与departments表,即连接dept_no与dept_name,得到所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工

select c.last_name,c.first_name,a.dept_name
from employees c left join dept_emp b on c.emp_no=b.emp_no
left join departments a on b.dept_no = a.dept_no

查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth(最大值减最小值)

select max(salary)-min(salary) as growth
from salaries
where emp_no=10001

查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序

基本思路:整合成一张表(id, 来的时候的工资,最后的工资)
这张表第二个字段和第三个字段都涉及到了salary
所以一定会级联两次表salaries
也就是employees join salaries join salaries之后用on把条件筛选一个就可以了
select a.emp_no, (b.salary - c.salary) as growth
from employees a inner join salaries as b
on a.emp_no = b.emp_no and b.to_date = '9999-01-01'
inner join salaries as c
on a.emp_no = c.emp_no and a.hire_date = c.from_date
order by growth 

统计各个部门对应员工涨幅的次数总和,给出部门编码dept_no、部门名称dept_name以及次数sum

关键是要将 每个部门分组,并分别统计工资记录总数,思路如下:
1、用INNER JOIN连接dept_emp表和salaries表,并以dept_emp.no分组,统计每个部门所有员工工资的记录总数
2、再将上表用INNER JOIN连接departments表,限制条件为两表的dept_no相等,找到dept_no与dept_name的对应关系,最后依次输出dept_no、dept_name、sum
select a.dept_no,a.dept_name,count(c.emp_no) as sum
from departments a inner join dept_emp b
on a.dept_no=b.dept_no
inner join salaries c 
on b.emp_no=c.emp_no
group by a.dept_no

对所有员工的当前(to_date='9999-01-01')薪水按照salary进行按照1-N的排名,相同salary并列且按照emp_no升序排列

主要思想是复用salaries表进行比较排名,具体思路如下:
1、从两张相同的salaries表(分别为s1与s2)进行对比分析,先将两表限定条件设为to_date = '9999-01-01',挑选出当前所有员工的薪水情况。
2、本题的精髓在于 s1.salary <= s2.salary,意思是在输出s1.salary的情况下,有多少个s2.salary大于等于s1.salary,比如当s1.salary=94409时,有3个s2.salary(分别为94692,94409,94409)大于等于它,但由于94409重复,利用COUNT(DISTINCT s2.salary)去重可得工资为94409的rank等于2。其余排名以此类推。
select s1.emp_no,s1.salary,count(distinct s2.salary)
from salaries s1,salaries 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 s1.salary desc,s2.emp_no asc

获取所有非manager员工当前的薪水情况,给出dept_no、emp_no以及salary ,当前表示to_date='9999-01-01'

select a.dept_no,a.emp_no,d.salary
from dept_emp a inner join salaries d on a.emp_no=d.emp_no
inner join dept_manager b on a.dept_no=b.dept_no
where a.to_date='9999-01-01' and d.to_date='9999-01-01' and a.emp_no != b.emp_no
或者
select a.dept_no,a.emp_no,(select salary from salaries where emp_no=a.emp_no and to_date='9999-01-01') as salary 
from dept_emp a left join dept_manager b on a.emp_no=b.emp_no
where a.to_date='9999-01-01' and b.emp_no is null
或者
select a.dept_no,a.emp_no,d.salary 
from dept_emp a inner join salaries d on a.emp_no = d.emp_no and d.to_date = '9999-01-01'
where a.emp_no not in (select emp_no from dept_manager where to_date = '9999-01-01')

获取员工其当前的薪水比其manager当前薪水还高的相关信息,当前表示to_date='9999-01-01',

结果第一列给出员工的emp_no,
第二列给出其manager的manager_no,
第三列给出该员工当前的薪水emp_salary,
第四列给该员工对应的manager当前的薪水manager_salary

1.将dept_emp 与salaries连接得到employee的工资表 a
2.将dept_manager与salaries连接得到manager的工资表 b
3.将员工工资表a与管理员工资表b按照 同部门且员工工资大于管理员工资的条件连接
select a.emp_no ,b.emp_no, a.salary, b.salary
from
(dept_emp join salaries on dept_emp.emp_no = salaries.emp_no and dept_emp.to_date ='9999-01-01' and salaries.to_date ='9999-01-01')as a
join
(dept_manager join salaries on dept_manager.emp_no = salaries.emp_no and dept_manager.to_date='9999-01-01' and salaries.to_date='9999-01-01')as b
on a.dept_no = b.dept_no and a.salary > b.salary

汇总各个部门当前员工的title类型的分配数目,结果给出部门编号dept_no、dept_name、其当前员工所有的title以及该类型title对应的数目count

难点在于group by进行分组的时候,先从大范围分,也就是部门编号,再在部门内分组以及当前日期的书写

select a.dept_no,a.dept_name,c.title,count(c.title) as count
from dept_emp b inner join departments a
on b.dept_no = a.dept_no
inner join titles c on b.emp_no = c.emp_no and b.to_date=c.to_date and c.to_date='9999-01-01'
group by a.dept_no,c.title

查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部

先将描述信息包含 “robot” 的电影分类及数量统计出来,再针对每一个分类,在 film_category 总表中该分类下所有电影的数量需要 >=5,最后筛选出满足条件的统计结果输出。
注意,统计出来 “robot” 的电影数量是多少就是多少,与 >=5 没有关系
select a.name,count(b.film_id) as count
from (select category_id from film_category group by category_id having count(category_id) >= 5) as cc , category a, film b , film_category c
where b.description like "%robot%" 
and cc.category_id=a.category_id
and c.film_id=b.film_id
and a.category_id=c.category_id

使用子查询的方式找出属于Action分类的所有电影对应的title,description

in和=均可
select a.title,a.description
from film_category c,film a
where c.film_id=a.film_id and c.category_id in (select category_id from category where name ="Action")

获取select * from employees对应的执行计划

用 "EXPLAIN" 关键字或 "EXPLAIN QUERY PLAN" 短语,用于描述表的细节,具体说明与用法可参考:
explain select * from employees

将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分

select last_name||" "||first_name as Name
from employees
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)
)
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 OR IGNORE 来插入记录,或忽略插入与表内UNIQUE字段都相同的记录
用 INSERT OR REPLACE 来插入记录,或更新替代与表内UNIQUE字段都相同的记录
INSERT OR IGNORE INTO actor VALUES (3, 'ED', 'CHASE', '2006-02-15 12:34:33')
create table 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 TRIGGER audit_log AFTER INSERT ON employees_test
BEGIN INSERT INTO audit VALUES (NEW.ID, NEW.NAME);
END

删除emp_no重复的记录,只保留最小的id对应的记录。

delete from titles_test
where id not in (select min(id) from titles_test)
直接使用REPLACE INTO的话,就需要重新插入一条完整的新纪录,sql会自动代替id相同的记录
REPLACE INTO titles_test VALUES (5, 10005, 'Senior Engineer', '1986-06-26', '9999-01-01')

将titles_test表名修改为titles_2017

ALTER TABLE titles_test RENAME TO titles_2017
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容