【SQL】牛客刷题笔记:SQL246~SQL254

1.SQL 246 获取employees的first_name

请你将employees中的first_name,并按照first_name最后两个字母升序进行输出。

该题与SQL213、SQL226、SQL244类似,都考察了字符串相关的函数。本题所考察的函数是字符串截取函数substr(str,index,len)。该函数用法如下:

subtring(字符串,截取的起始位置,截取的字符数)

index从1开始,第三个参数可以省略,表示截取到最后一位

本题中要求从从末尾截取,从后往前数使用负数表示。

sql 复制代码
select first_name
from employees 
order by substr(first_name,-2)

2.SQL 247 按照dept_no进行汇总

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

改题目仍旧属于对字符串函数的考察 ,这里使用的函数是g**roup_concat()。**该函数可以字段进行连接,并按照排序字段的顺序用分隔符隔开。具体用法如下:

group_concat([distinct] 字段 [order by 排序字段 asc/desc] separator '分隔符')

separator字段也可以省略,省略则代表使用默认分隔符","

sql 复制代码
select dept_no,group_concat(emp_no) as employees
from dept_emp
group by dept_no

3.SQL 248 平均工资

查找排除在职(to_date = '9999-01-01' )员工的最大、最小salary之后,其他的在职员工的平均工资avg_salary。

本题需要求平均工资,但限定了员工范围为在职员工(to_date = '9999-01-01'),且不考虑最大值和最小值。

在职员工这个限定条件可以通过where子句 根据to_date的值进行筛选,去除不符合条件的。同样,最大值和最小值也可以通过not in 关键字 排除**,注意因为工资最高或最低的员工可能不止一名,存在工资数相同的情况,因此不能用!=筛选。**

本题考察的函数主要是**max()和min()**函数,这两个函数比较简单,不过多介绍。

sql 复制代码
select avg(salary) 
from salaries
where to_date = "9999-01-01"
and salary not in (select max(salary) from salaries where to_date  = "9999-01-01")
and salary not in  (select min(salary) from salaries where to_date ="9999-01-01")

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

本题考查分页查询,分页查询也是在业务场景中经常遇到的情况,使用**limit()**函数即可解决。

limit x, y: x:表示偏移量(从0开始), y:表示获取的数据数量

**计算分页的公式:**limit (页数-1)*每页显示行数,每页显示行数

sql 复制代码
select * from employees limit 5,5

5.SQL 251 使用exists关键字查找未分配具体部门的员工

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

本题的常规解答是使用in关键字判断是否存在:

sql 复制代码
SELECT * FROM employees WHERE emp_no NOT IN (SELECT emp_no FROM dept_emp);

但本题中限定了需要使用exists关键字。exists的原理是:

exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当 exists里的条件语句能够返回记录行时,条件就为真,返回当前loop到的这条记录;反之如果exists里的条件语句不能返回记录行,则当前loop到的这条记录被丢弃。

也就是说,在 employees中挑选出exists条件不成立的记录。

sql 复制代码
select employees.*
from employees
where not exists (
    select emp_no
    from dept_emp
    where emp_no = employees.emp_no
)

补充:什么时候用EXISTS,什么时候用IN?

当主表比从表大时,IN查询的效率较高;

当从表比主表大时,EXISTS查询的效率较高;

6.SQL 253 获取有奖金的员工相关信息

bonus类型btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%。 to_date='9999-01-01'表示当前薪水。

请你给出emp_no、first_name、last_name、奖金类型btype、对应的当前薪水情况salary以及奖金金额bonus。

bonus结果保留一位小数,输出结果按emp_no升序排序。

本题的难点在于多表连接,以及对奖金金额的计算。需要注意的是对薪水的查询限定了是当前的薪水情况( to_date='9999-01-01')。

多表链接比较简单,外连接就可以:

sql 复制代码
select e.emp_no ,first_name,last_name,b.btype,s.salary   
from employees e
join salaries s
using(emp_no)
join emp_bonus b
using(emp_no)
where s.to_date ="9999-01-01"

比较麻烦的是对于奖金的计算,btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%,也就是要根据bytpe的值,要分情况讨论,也就是case when。

CASE

WHEN condition THEN result

[WHEN...THEN...]

ELSE result

END

condition是一个返回布尔类型的表达式,如果返回true,则整个函数返回相应result的值,如果表达式均为false,则返回ElSE result的值,若ELSE子句省略,则返回NULL。

sql 复制代码
select e.emp_no ,first_name,last_name,b.btype,s.salary,round((
    case btype
    when 1 then (s.salary )*0.1
    when 2 then (s.salary) *0.2
    else (s.salary) *0.3
    end
),1) as bonus
from employees e
join salaries s
using(emp_no)
join emp_bonus b
using(emp_no)
where s.to_date ="9999-01-01"

这里还有一个小细节,就是需要对计算出的奖金保留1位小数。直接使用**round(值,保留位数)**进行处理即可。

7.SQL 254 统计salary的累计和running_total

按照salary的累计和running_total,其中running_total为前N个当前( to_date = '9999-01-01')员工的salary累计和,其他以此类推。

这道题要求计算累加和,提到"累加",自然就能想到窗口函数。窗口函数在SQL里应用很广,关于它的具体使用,后期我再详细写一篇和大家分享,其实并不是很难。窗口函数的语法格式如下:

<窗口函数> over (partition by <用于分组的列名> order by <用于排序的列名>)

sql 复制代码
select emp_no ,salary,sum(salary) over(order by emp_no)
from salaries
where to_date ="9999-01-01"

这里先简单解释一下本题的思路。使用窗口函数对salary列进行累加求和,sum() over()即为求和,salary是需要求和的列,本题中并不需要进行分组(例如学生成绩表,需要对学生按照班级进行排名,这时就需要用到分组),只需要按照emp_no进行排序就可以了(排序一定要有的,毕竟是计算累加和,如果无序的话就成了计算所有的和了)。

这里再分享一个没有用到窗口函数的方法:

sql 复制代码
SELECT s2.emp_no,s2.salary,SUM(s1.salary) AS running_total
FROM salaries AS s1 INNER JOIN salaries AS s2
ON s1.emp_no <= s2.emp_no
WHERE
s1.to_date = "9999-01-01"
AND s2.to_date = "9999-01-01"
GROUP BY s2.emp_no
相关推荐
亦枫Leonlew1 分钟前
微积分复习笔记 Calculus Volume 2 - 5.1 Sequences
笔记·数学·微积分
sdaxue.com33 分钟前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
爱码小白34 分钟前
网络编程(王铭东老师)笔记
服务器·网络·笔记
LuH11241 小时前
【论文阅读笔记】Learning to sample
论文阅读·笔记·图形渲染·点云
o(╥﹏╥)1 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长2 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_2 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
Sunyanhui12 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记2 小时前
MHA binlog server
数据库·mysql