【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
相关推荐
Arbori_2621513 分钟前
获取oracle表大小
数据库·oracle
lulinhao17 分钟前
HCIA/HCIP基础知识笔记汇总
网络·笔记
王强你强19 分钟前
MySQL 高级查询:JOIN、子查询、窗口函数
数据库·mysql
草巾冒小子20 分钟前
brew 安装mysql,启动,停止,重启
数据库·mysql
用户62799471826227 分钟前
南大通用GBase 8c分布式版本gha_ctl 命令-HI参数详解
数据库
斯汤雷35 分钟前
Matlab绘图案例,设置图片大小,坐标轴比例为黄金比
数据库·人工智能·算法·matlab·信息可视化
SQLplusDB42 分钟前
Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误
数据库·oracle·embedding
杉之1 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
喝醉酒的小白1 小时前
SQL Server 可用性组自动种子设定失败问题
数据库
chem41111 小时前
Conmon lisp Demo
服务器·数据库·lisp