牛客网sql实战(三)

28.查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部
不是很明白?
根据题意,需要有四张表

  • 题目所给的三张表:film,category,film_category
  • 另外需要一张每个分类对应的电影数量>=5的电影分类表
select c.name,count(*) from 
(select category_id from film_category
group by category_id having count(category_id)>=5) as a,
film as b,category as c,film_category as d
where b.film_id=d.film_id
and c.category_id=d.category_id
and a.category_id=d.category_id
and b.description like '%robot%';

29.使用join查询方式找出没有分类的电影id以及名称
本题不需要用到category表,将film表左连接film_category,再筛选出category_id为null的记录,即为没有分类的电影

select f.film_id,f.title from film as f left join film_category as fc
on f.film_id=fc.film_id where fc.category_id is null

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

  • 第一步:找到所有属于action分类的电影id
  • 第二步:根据得到的电影id得到对应的电影信息
-- 根据得到的电影id得到对应的电影信息
select title,description from film where film_id in(
-- 找到所有属于action分类的电影id
select fc.film_id from film_category as fc inner join category c on fc.category_id=c.category_id
where c.name='Action')

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

explain select * from employees;

32.将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分
sqllite连接字符串的写法:

select last_name||" "||first_name as name  from employees

mysql下可以用concat:

select concat(last_name,' ',first_name) as name from employees;

33.创建一个actor表,包含如下列信息
注意:DEFAULT (datetime('now','localtime')) 设置默认值为系统的当前时间

create table 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)
);

34.对于表actor批量插入如下数据

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

35.对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作
sqllite3的做法:

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_name表,将actor表中的所有first_name以及last_name导入改表

create table actor_name as select first_name,last_name from actor;

37.针对如下表actor结构创建索引:
对first_name创建唯一索引uniq_idx_firstname,对last_name创建普通索引idx_lastname

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

解法:

create unique index uniq_idx_firstname on actor(first_name);
create index idx_lastname on actor(last_name);

38.针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v
方法一:

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;

知识点补充:

什么是视图?
视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询
视图仅仅是用来查看存储在别处的数据的一种设施,本身不包含数据,因此返回的数据是从其他表中检索出来的,在添加或更改这些表中的数据时,视图将返回改变过的数据
视图的使用
create view 用于 创建视图
show create view viewname 查看创建视图的语句
drop view viewname删除视图
更新视图:方式1:先drop再create;方式2:create or replace view

39.针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引

sqllite的解法:

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

存在actor表,包含如下列信息:
现在在last_update后面新增加一列名字为create_date, 类型为datetime, NOT NULL,默认值为'0000-00-00 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')));

解法:

alter table actor add create_date datetime not null default('0000-00-00 00:00:00');

注意:修改表中的记录使用update,更改表中的结构使用alter
40.构造一个触发器audit_log,在向employees_test表中插入一条数据的时候,触发插入相关的数据到audit中

create trigger audit_log after insert on employees_test
begin
insert into audit (EMP_no,NAME) values(NEW.ID,NEW.NAME);
end; 

知识点补充:
什么是触发器?

在某个表发生更改时自动处理,是mysql响应以下任意语句而自动执行的一条mysql语句

  • delete
  • insert
  • update

创建触发器的注意事项:

  • 唯一的触发器名
  • 触发器关联的表
  • 触发器应该响应的活动(delete、insert或update)
  • 触发器何时执行
    41.删除emp_no重复的记录,只保留最小的id对应的记录
delete from titles_test where id not in 
(select min(id) from titles_test group by emp_no)

42.将所有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'

43.将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。

update titles_test set emp_no=replace(emp_no,10001,10005) where id=5;

44.将titles_test表名修改为titles_2017

-- rename table titles_test to titles_2017;
ALTER TABLE titles_test RENAME TO titles_2017

45.在audit表上创建外键约束,其emp_no对应employees_test表的主键id

DROP TABLE audit;
CREATE TABLE audit(
    EMP_no INT NOT NULL,
    create_date datetime NOT NULL,
    FOREIGN KEY(EMP_no) REFERENCES employees_test(ID));

46.存在如下的视图:
create view emp_v as select * from employees where emp_no >10005;
如何获取emp_v和employees有相同的数据

select b.* from emp_v as a,employees as b where a.emp_no=b.emp_no

注意:需要在前加上表的显示,不然同时得到两张表的重复记录*
47.将所有获取奖金的员工当前的薪水增加10%。

update salaries set salary=salary*1.1 where emp_no in (
    select a.emp_no from emp_bonus as a inner join salaries as b on 
a.emp_no=b.emp_no and b.to_date='9999-01-01')

48.针对库中的所有表生成select count()对应的SQL语句*
sqlite写法:

select "select count(*) from "||name||";" as cnts
    from sqlite_master 
    where type='table';

mysql写法:

select concat("select count(*) from ",table_name,";") as cnts
from (select table_name from information_schema.columns) as new

49.将employees表中的所有员工的last_name和first_name通过(')连接起来
sqlite写法:

select last_name||"'"||first_name from employees;

mysql写法:

select concat(last_name,"'",first_name) from employees;

50.查找字符串'10,A,B' 中逗号','出现的次数cnt

select (length('10,A,B')-length(replace('10,A,B',',','')))/length(',') as cnt

51.获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列

  • substr语法:参数一:目标串;参数二:+表示从左往右数,-表示从右往左数;参数三:截取的长度
select first_name from employees order by substr(first_name,-2,2)

52.按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees

select dept_no,group_concat(emp_no,',') from dept_emp
group by dept_no

53.查找排除当前最大、最小salary之后的员工的平均工资avg_salary

select avg(salary) as avg_salary from salaries where to_date='9999-01-01'
and salary<>(select min(salary) from salaries where to_date='9999-01-01')
and salary<>(select max(salary) from salaries where to_date='9999-01-01');

54.分页查询employees表,每5行一页,返回第2页的数据

select * from employees limit 5,5

55.获取所有员工的emp_no、部门编号dept_no以及对应的bonus类型btype和received ,没有分配具体的员工不显示

  • 先得到分配了部门的员工信息与部门信息的表,使用内连接
  • 在将上表与bonus表进行左连接,没有bonus信息的地方不显示
select a.emp_no,b.dept_no,c.btype,c.recevied 
from employees as a 
inner join dept_emp as b on a.emp_no=b.emp_no
left join emp_bonus as c on a.emp_no=c.emp_no;

56.使用含有关键字exists查找未分配具体部门的员工的所有信息

select a.* from employees as a where not exists 
(select emp_no from dept_emp where emp_no=a.emp_no)

57.给出emp_no、first_name、last_name、奖金类型btype、对应的当前薪水情况salary以及奖金金额bonus。 bonus类型btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%。

case语句的使用:

case (条件变量)
when (条件值一) then (内容)
when (条件值二) then (内容)
、、、
else (内容) end

select a.emp_no,a.first_name,a.last_name,b.btype,c.salary,
(case b.btype
 when 1 then c.salary*0.1
 when 2 then c.salary*0.2
 else c.salary*0.3 end
)as bonus
from employees as a 
inner join emp_bonus as b 
on a.emp_no=b.emp_no
inner join salaries as c on a.emp_no=c.emp_no
where c.to_date='9999-01-01'

58.按照salary的累计和running_total,其中running_total为前两个员工的salary累计和

select a.emp_no,a.salary,
(select sum(b.salary) from salaries as b 
 where b.emp_no<=a.emp_no and b.to_date='9999-01-01') 
as running_total 
from salaries as a 
where a.to_date='9999-01-01' order by a.emp_no; 

59.对于employees表中,给出奇数行的first_name

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

推荐阅读更多精彩内容