牛客网数据库SQL实战解析(51-61题)

牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0

牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010666669/article/details/104763370

牛客网数据库SQL实战解析(11-20题): https://blog.csdn.net/u010666669/article/details/104863298

牛客网数据库SQL实战解析(21-30题): https://blog.csdn.net/u010666669/article/details/104871373

牛客网数据库SQL实战解析(31-40题): https://blog.csdn.net/u010666669/article/details/104977904

牛客网数据库SQL实战解析(41-50题): https://blog.csdn.net/u010666669/article/details/104979427

牛客网数据库SQL实战解析(51-61题): https://blog.csdn.net/u010666669/article/details/104980372

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

SELECT (length("10,A,B")-length(replace("10,A,B",",","")))/length(",") AS cnt ;

解析:找出所有,的长度,再除以一个,的长度。

 

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

SELECT first_name 
FROM employees 
ORDER BY substr(first_name,length(first_name)-1)
;

题解二:

SELECT first_name FROM employees ORDER BY substr(first_name,-2);

解析:字符串截取,substring()。

 

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

SELECT dept_no, group_concat(emp_no) AS employees
FROM dept_emp GROUP BY dept_no
;

解析:聚合函数group_concat(X,Y),其中X是要连接的字段,Y是连接时用的符号,可省略,默认为逗号。此函数必须与 GROUP BY 配合使用。此题以 dept_no 作为分组,将每个分组中不同的emp_no用逗号连接起来(即可省略Y)。

 

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

SELECT AVG(salary) AS avg_salary FROM salaries 
WHERE to_date = '9999-01-01' 
AND salary NOT IN (SELECT MAX(salary) FROM salaries)
AND salary NOT IN (SELECT MIN(salary) FROM salaries)
;

解析:这题逻辑很简单。

 

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

SELECT * FROM employees LIMIT 5,5 ;

解析:分页可以通过limit来实现:limit  x, y: x:表示偏移量, y:表示获取的数据数量

 

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

SELECT de.emp_no, de.dept_no, eb.btype, eb.recevied
FROM dept_emp AS de LEFT JOIN emp_bonus AS eb 
ON de.emp_no = eb.emp_no
;

解析:一个无聊的题。

 

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

SELECT * 
FROM employees 
WHERE NOT EXISTS(
    SELECT emp_no 
    FROM dept_emp 
    WHERE emp_no = employees.emp_no
)
;

解析:exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当 exists里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录;反之如果exists里的条 件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为 false。

 

58. 获取employees中的行数据,且这些行也存在于emp_v中。注意不能使用intersect关键字。

SELECT em.* 
FROM employees em, emp_v ev 
WHERE em.emp_no = ev.emp_no
;

解析:。。。

 

59. 获取有奖金的员工相关信息。

SELECT e.emp_no, 
       e.first_name, 
       e.last_name, 
       b.btype, 
       s.salary, 
      (CASE b.btype 
       WHEN 1 THEN s.salary * 0.1
       WHEN 2 THEN s.salary * 0.2
       ELSE s.salary * 0.3 END) AS bonus
FROM employees AS e 
INNER JOIN emp_bonus AS b 
   ON e.emp_no = b.emp_no
INNER JOIN salaries AS s 
   ON e.emp_no = s.emp_no AND s.to_date = '9999-01-01'
;

解析:CASE 表达式的用法。即当 btype = 1 时,得到 salary * 0.1;当 btype = 2 时,得到 salary * 0.2;其他情况得到 salary * 0.3。

 

60. 按照salary的累计和running_total,其中running_total为前两个员工的salary累计和,其他以此类推。

SELECT s1.emp_no, 
       s1.salary, 
       (SELECT SUM(s2.salary) 
        FROM salaries AS s2 
        WHERE s2.emp_no <= s1.emp_no AND s2.to_date = '9999-01-01') AS running_total 
FROM salaries AS s1 
WHERE s1.to_date = '9999-01-01' 
ORDER BY s1.emp_no
;

解析:输出的第三个字段,是由一个 SELECT 子查询构成。将子查询内复用的 salaries 表记为 s2,主查询的 salaries 表记为 s1,当主查询的 s1.emp_no 确定时,对子查询中不大于 s1.emp_no 的 s2.emp_no 所对应的薪水求和。

 

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

SELECT first_name FROM  ( 
    SELECT e2.first_name,
          ( SELECT COUNT(*) 
            FROM employees e1 
            WHERE e1.first_name <= e2.first_name 
          )  AS rownum 
    FROM employees e2 
    WHERE rownum % 2 =1 
) t
;

解析:计算行号的方法 : 有多少个小于等于e2.first_name的记录的个数就是e2.first_name的行号

你可能感兴趣的:(SQL)