牛客網SQL刷題記錄

文章目錄

查找最晚入職員工的所有信息

select * 
from employees
order by hire_date desc limit 1;

查找入職員工時間排名倒數第三的員工所有信息

select * from employees
order by hire_date desc limit 2,1;

查找各個部門當前(to_date=‘9999-01-01’)領導當前薪水詳情以及其對應部門編號dept_no

select s.*,d.dept_no
from salaries as s inner join dept_manager as d
on s.to_date='9999-01-01'
and d.to_date='9999-01-01'
and s.emp_no=d.emp_no

查找所有已經分配部門的員工的last_name和first_name,dept_no

select e.last_name,e.first_name,d.dept_no
from employees as e inner join dept_emp as d
on e.emp_no=d.emp_no

查找所有員工的last_name和first_name以及對應部門編號dept_no,也包括展示沒有分配具體部門的員工

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

查找所有員工入職時候的薪水情況,給出emp_no以及salary, 並按照emp_no進行逆序

select e.emp_no,s.salary
from employees as e inner join salaries as s
on e.emp_no=s.emp_no
and e.hire_date=s.from_date
order by e.emp_no desc

查找薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t?

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

找出所有員工當前(to_date=‘9999-01-01’)具體的薪水salary情況,對於相同的薪水只顯示一次,並按照逆序顯示

select distinct salary
from salaries
where to_date='9999-01-01'
order by salary desc

獲取所有部門當前manager的當前薪水情況,給出dept_no, emp_no以及salary,當前表示to_date=‘9999-01-01’

select d.dept_no,d.emp_no,s.salary
from dept_manager as d,salaries as s
where d.emp_no=s.emp_no
and d.to_date='9999-01-01'
and s.to_date='9999-01-01'

獲取所有非manager的員工emp_no

select emp_no
from employees
where emp_no not in (select emp_no from dept_manager)

獲取所有員工當前的manager,如果當前的manager是自己的話結果不顯示,當前表示to_date=‘9999-01-01’。結果第一列給出當前員工的emp_no,第二列給出其manager對應的manager_no。?

select dp.emp_no,dm.emp_no
from dept_emp as dp inner join dept_manager as dm
on dp.dept_no=dm.dept_no
and dp.emp_no<>dm.emp_no
and dm.to_date='9999-01-01'
and dp.to_date='9999-01-01'

獲取所有部門中當前員工薪水最高的相關信息,給出dept_no, emp_no以及其對應的salary

select d.dept_no,d.emp_no,max(s.salary)
from dept_emp as d inner join salaries as s
on d.emp_no=s.emp_no
and d.to_date='9999-01-01'
and s.to_date='9999-01-01'
group by d.dept_no

從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。

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

從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。注意對於重複的title進行忽略。?

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

查找employees表所有emp_no爲奇數,且last_name不爲Mary的員工信息,並按照hire_date逆序排列

select * 
from employees 
where emp_no%2=1
and last_name<>'Mary'
order by hire_date desc;

統計出當前各個title類型對應的員工當前(to_date=‘9999-01-01’)薪水對應的平均工資。結果給出title以及平均工資avg。

select t.title,avg(s.salary) as avg
from titles as t,salaries as s
where s.to_date='9999-01-01'
and t.to_date='9999-01-01'
and s.emp_no=t.emp_no
group by t.title

獲取當前(to_date=‘9999-01-01’)薪水第二多的員工的emp_no以及其對應的薪水salary

select emp_no,max(salary)
from salaries
where to_date='9999-01-01'
and salary not in (select max(salary) from salaries)

或者

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 s.emp_no,max(s.salary),e.last_name,e.first_name
from salaries as s,employees as e
where s.emp_no=e.emp_no
and s.to_date='9999-01-01'
and s.salary not in (select max(salary) from salaries)

查找所有員工的last_name和first_name以及對應的dept_name,也包括暫時沒有分配部門的員工

select e.last_name,e.first_name,d.dept_name
from employees as e left join dept_emp as dp
on e.emp_no=dp.emp_no
left join departments as d
on d.dept_no=dp.dept_no

查找員工編號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 limit 1)
as growth

查找所有員工自入職以來的薪水漲幅情況,給出員工編號emp_no以及其對應的薪水漲幅growth,並按照growth進行升序?

select a.emp_no,(b.salary-c.salary)as growth
from employees as 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 c.emp_no=b.emp_no
and a.hire_date=c.from_date
order by growth

統計各個部門對應員工漲幅的次數總和,給出部門編碼dept_no、部門名稱dept_name以及次數sum

答案

select dp.dept_no,d.dept_name,count(s.salary)as sum
from dept_emp as dp,departments as d,salaries as s
where d.dept_no=dp.dept_no
and dp.emp_no=s.emp_no
group by d.dept_no

自己寫的(屬實垃圾)?

select d.dept_no,d.dept_name,new.sum
from departments as d
inner join 
(select dp.dept_no,count(s.salary) as sum
from dept_emp as dp,salaries as s
where dp.emp_no=s.emp_no
group by dp.dept_no)as new
on d.dept_no=new.dept_no

對所有員工的當前(to_date=‘9999-01-01’)薪水按照salary進行按照1-N的排名,相同salary並列且按照emp_no升序排列

自己寫的,屬實優秀??

select emp_no,salary,dense_rank() over (order by salary desc)
from salaries
where to_date='9999-01-01'

答案寫的

select s1.emp_no,s1.salary,count(distinct s2.salary) rank
from salaries s1, salaries s2
where s1.salary <= s2.salary and s1.to_date = '9999-01-01' and s2.to_date = '9999-01-01'
group by s1.emp_no order by rank;

獲取所有非manager員工當前的薪水情況,給出dept_no、emp_no以及salary ,當前表示to_date=‘9999-01-01’

select dp.dept_no,dp.emp_no,s.salary
from dept_emp as dp,salaries as s
where dp.emp_no not in (select emp_no from dept_manager where to_date='9999-01-01')
and dp.emp_no = s.emp_no
and dp.to_date='9999-01-01'
and s.to_date='9999-01-01'

獲取員工其當前的薪水比其manager當前薪水還高的相關信息,當前表示to_date=‘9999-01-01’,結果第一列給出員工的emp_no,

第二列給出其manager的manager_no,

第三列給出該員工當前的薪水emp_salary,

第四列給該員工對應的manager當前的薪水manager_salary

select a.emp_no,b.emp_no as manager_no,a.salary as emp_salary,b.salary as manager_salary
from 
(select dp.emp_no,dp.dept_no,s.salary
from dept_emp as dp,salaries as s
where dp.emp_no=s.emp_no
and s.to_date='9999-01-01'
and dp.emp_no not in (select emp_no from dept_manager))as a,
(select dm.emp_no,dm.dept_no,s.salary
from dept_manager as dm,salaries as s
where dm.emp_no=s.emp_no
and s.to_date='9999-01-01')as b
where a.salary>b.salary
and a.dept_no=b.dept_no

本題思想,製作兩張表,一個員工表,一個經理表

彙總各個部門當前員工的title類型的分配

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

自己寫的

select d.dept_no,d.dept_name,t.title,count(t.emp_no)as count
from departments as d,dept_emp as dp,titles as t
where d.dept_no=dp.dept_no
and dp.emp_no=t.emp_no
and dp.to_date='9999-01-01'
and t.to_date='9999-01-01'
group by d.dept_no,t.title

給出每個員工每年薪水漲幅超過5000的信息

select s2.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

查找描述信息中包含robot的電影對應的分類名稱以及電影數目,而且還需要該分類的電影數目>=5部

select c.name,count(fc.film_id)
from (select category_id,count(film_id)as category_num from film_category group by category_id having count(film_id)>=5) as cc,
film as f,
category as c,
film_category as fc
where f.description like'%robot%'
and f.film_id=fc.film_id
and c.category_id=fc.category_id
and cc.category_id=c.category_id

使用join查詢方式找出沒有分類的電影id以及名稱

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

使用子查詢的方式找出屬於Action分類的所有電影對應的title,description

select f.title,f.description
from film as f,(select fc.film_id from film_category as fc,category as c
               where c.category_id=fc.category_id
               and c.name='Action')as new
where f.film_id=new.film_id

這個是自己寫的

select title,description
from film 
where film.film_id in
(select fc.film_id from film_category as fc,category as c
 where c.category_id=fc.category_id 
 and c.name='Action')

以下這兩個都是網上的

select title,description 
from film 
where film.film_id in 
(select film_id 
from film_category
where category_id in (
select category_id 
from category 
where name='Action'))

select title,description 
from film 
where film.film_id in 
(select film_id 
from film_category
where category_id in (
select category_id 
from category 
where name='Action'))

將employees表的所有員工的last_name和first_name拼接起來作爲Name,中間以一個空格區分。

這是sqlite的方法

select last_name||" "|| first_name
from employees 

這是mysql的方法

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

創建一個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'))
);

對於表actor批量插入如下數據,如果數據已經存在,請忽略,不使用replace操作

INSERT or ignore INTO ACTOR
(actor_id,first_name,last_name,last_update)
values(
    3,'ED','CHASE','2006-02-15 12:34:33'
)

創建一個actor_name表,將actor表中的所有first_name以及last_name導入該表。

在這裏插入圖片描述

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 unique index 索引名 on 表名(某列名)

創建普通索引

create index 索引名 on 表名(某列名)

在這裏插入圖片描述

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

創建視圖

我覺得視圖就像是一個虛擬新表,後來執行查詢時就可以在這個虛擬新表中進行。

create view 視圖名 as
select ...
from...
...

在這裏插入圖片描述

create view actor_name_view as 
select first_name as first_name_v,last_name as last_name_v
from actor;

使用強制索引

mysql

select|delete|update column1,column2,...
forced index index_name
where (condition);

sqlite

select|delete|update column1,column2,...
from table_name
indexed by index_name
where (condition);

增加新列

alter table table_name
add column column_name type ...,
add column column_name type ...;

在這裏插入圖片描述

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

創建觸發器

在這裏插入圖片描述

create trigger audit_log after insert on employees 
begin
insert into audit values(new.id,new.name);
end;

刪除某條記錄

delete from table_name
where (condition)

在這裏插入圖片描述

delete from titles_test
where id not in (select min(id) from titles_test group by emp_no);

更新數據

update table_name
set
更新要求1,
更新要求2,
...
where(condition)

在這裏插入圖片描述

update titles_test
set
to_date=NULL,
from_date='2001-01-01'
where to_date='9999-01-01';

replace用法

update table_name
set column_name=replace(column_name,str1,str2)
where(condition)

把表的column_name列的str1替換爲str2
在這裏插入圖片描述

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

表名重命名?

alter table table_name
rename [to|as] new_table_name;

或者(但是下面這種在牛客網上不通過,在mysql上可以通過)

rename table table_name to new_table_name;

修改表名,to或as都可以,也可省略to或as
在這裏插入圖片描述

alter table titles_test
rename titles_2017;

外鍵約束

將所有獲取獎金的員工當前的薪水增加10%。
在這裏插入圖片描述

update salaries
set salary=salary*1.1
where emp_no in (select emp_no from emp_bonus)
and to_date='9999-01-01'

針對庫中的所有表生成select count(*)對應的sql語句。

在這裏插入圖片描述

這題答案是用sqlite寫的

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

1.在 SQLite 系統表 sqlite_master 中可以獲得所有表的索引,其中字段 name 是所有表的名字,而且對於自己創建的表而言,字段 type 永遠是 ‘table’,詳情可參考:博客

2.在 SQLite 中用 “||” 符號連接字符串

mysql寫法:

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

這裏要注意必須給from後面的這個表加一個別名,不然會出現every derived table must has its own alias的錯誤。

將employees表中的所有員工的last_name和first_name通過(‘)連接起來。

myql寫法:

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

sqlite寫法:

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

字符,字節等

1個漢字=1個字=1個字符

一個字母=一個字符=1個字節

1個字符=1個字節=8bit(ASCII碼)

1個字符=2個字節=16bit(Unicode碼下)

1個字符=3個字節(utf-8)

length()計算的是字節長度

char_length()計算的是字符長度
在這裏插入圖片描述
查找字符串’10,A,B‘中逗號’,'出現的次數cnt.

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

substr()函數

substr(str,pos),從postion位置開始的往後的所有字符
substr(str from pos),同上
substr(str,pos,len),從position位置開始的往後的len個字符

在這裏插入圖片描述

select first_name
from employees
order by substr(first_name,-2);
或者:
select first_name
from employees
order by substr(first_name,-2,2);

group_concat()函數

官方文檔
在這裏插入圖片描述
例子:
在這裏插入圖片描述
按班級進行彙總,把同一班級的用逗號隔開。group_concat()默認是用逗號隔開的
在這裏插入圖片描述
在這裏插入圖片描述

牛客網題目:按照dept_no彙總,屬於同一個部門的emp_no按照逗號進行連接,結果給出dept_no以及連接出的結果employees.
在這裏插入圖片描述

select dept_no,group_concat(emp_no)as employees
from dept_emp
group by dept_no;

查找排除當前最大、最小salary之後的員工平均工資avg_salary.

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

分頁查詢

select column_1,column_2 from table_name limit 偏移量,查詢條數;

分頁查詢employees,每5行一頁,返回第2頁的數據

select * from employees limit 5,5;

偏移量從0計數 ,每5行一頁,那麼第2頁的數據是6-10行,所以limit5,5是從第6行起查詢5條數據

獲取所有員工的emp_no、部門編號dept_no以及對應的bonus類型btype和received ,沒有分配具體的員工不顯示

select e.emp_no,dp.dept_no,eb.btype,eb.recevied
from employees as e inner join dept_emp as dp 
on e.emp_no=dp.emp_no
left join emp_bonus as eb
on dp.emp_no=eb.emp_no;

使用含有關鍵字exists查找未分配具體部門的員工的所有信息。

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

獲取有獎金的員工相關信息。

給出emp_no、first_name、last_name、獎金類型btype、對應的當前薪水情況salary以及獎金金額bonus。 bonus類型btype爲1其獎金爲薪水salary的10%,btype爲2其獎金爲薪水的20%,其他類型均爲薪水的30%。 當前薪水錶示to_date=‘9999-01-01’。

考察case when用法。

case column_name
when column_name滿足某條件 then
when···
else ···
end

答案

select eb.emp_no,e.first_name,e.last_name,eb.btype,s.salary,
(case eb.btype
when 1 then s.salary*0.1
when 2 then s.salary*0.2
else s.salary*0.3
end)as bonus
from emp_bonus as eb,employees as e,salaries as s
where eb.emp_no=e.emp_no
and eb.emp_no=s.emp_no
and s.to_date='9999-01-01';

我自己寫的

select bb.emp_no,e.first_name,e.last_name,bb.btype,bb.salary,bb.bonus
from (select eb.emp_no,eb.btype,s.salary,
(case eb.btype
when 1 then s.salary*0.1
when 2 then s.salary*0.2
else s.salary*0.3
end
)as bonus
from emp_bonus as eb inner join salaries as s
on eb.emp_no = s.emp_no
and s.to_date='9999-01-01') as bb
inner join employees as e
on bb.emp_no=e.emp_no;

按照salary的累計和running_total,其中running_total爲前兩個員工的salary累計和,其他以此類推。

在這裏插入圖片描述

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

對於employees表中,給出奇數行的first_name.

select first_name
from employees as a
where (select count(*) from employees as b
      where b.first_name>=a.first_name)%2=1;

自己寫的(牛客網上不通過,但是mysql上可以通過)

select first_name
from employees,(select @rownum:=0)as r
where (@rownum:=@rownum+1)%2=1;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章