牛客的在线sq编程l题

1、查到倒数第三的那条数据

知识盲点:排序,limit ,offset

来源:https://blog.csdn.net/cnwyt/article/details/81945663

SQL查询语句中的 limit 与 offset 的区别:

  • limit y 分句表示: 读取 y 条数据

  • limit x, y 分句表示: 跳过 x 条数据,读取 y 条数据

  • limit y offset x 分句表示: 跳过 x 条数据,读取 y 条数据

查找入职员工时间排名倒数第三的员工所有信息,为了减轻入门难度,目前所有的数据里员工入职的日期都不是同一天
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

答案:

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

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

2、多表查询、排序

查找各个部门当前(dept_manager.to_date='9999-01-01')领导当前(salaries.to_date='9999-01-01')薪水详情以及其对应部门编号dept_no
(注:请以salaries表为主表进行查询,输出结果以salaries.emp_no升序排序,并且请注意输出结果里面dept_no列是最后一列)
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL, -- '员工编号',
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL, -- '部门编号'
`emp_no` int(11) NOT NULL, --  '员工编号'
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

select salaries.*, dept_manager.dept_no from 
salaries,dept_manager on salaries.emp_no = dept_manager.emp_no
where dept_manager.to_date='9999-01-01' and salaries.to_date='9999-01-01'  
order by salaries.emp_no asc;

3、各种join的用法

查找所有已经分配部门的员工的last_name和first_name以及dept_no(请注意输出描述里各个列的前后顺序)
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

引用:https://blog.csdn.net/zhengsy_/article/details/90733864

常见的join连接:

  • INNER JOIN :INNER JOIN等价于 JOIN,可以理解为 JOIN是 INNER JOIN 的缩写
  • JOIN: 如果表中有至少一个匹配,则返回行
  • LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN: 只要其中一个表中存在匹配,就返回行

引用两个表

可以通过引用两个表的方式,从两个表中获取数据:
select b.last_name,b.first_name,a.dept_no
from dept_emp a , employees  b where a.emp_no=b.emp_no;

inner join:

INNER JOIN 与 JOIN 是相同的,在表中存在至少一个匹配时,INNER JOIN 关键字返回行。左右表都能匹配的才会返回。

牛客的在线sq编程l题_第1张图片

这个总是记不住,看一下链接里面的例子

https://www.w3school.com.cn/sql/sql_join_inner.asp
select employees.last_name,employees.first_name,dept_emp.dept_no from employees 
inner join dept_emp on dept_emp.emp_no = employees.emp_no ;

题:

获取所有部门当前(dept_manager.to_date='9999-01-01')manager的当前(salaries.to_date='9999-01-01')薪水情况,给出dept_no, emp_no以及salary(请注意,同一个人可能有多条薪水情况记录)
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

select dept_manager.dept_no,dept_manager.emp_no,salaries.salary from dept_manager
inner join salaries on dept_manager.emp_no = salaries.emp_no
where salaries.to_date='9999-01-01' and dept_manager.to_date='9999-01-01'
 

left join:

关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。

牛客的在线sq编程l题_第2张图片

https://www.w3school.com.cn/sql/sql_join_left.asp

还是上面的那个题:

查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括暂时没有分配具体部门的员工(请注意输出描述里各个列的前后顺序)

select employees.last_name,employees.first_name,dept_emp.dept_no from employees 
left join dept_emp on employees.emp_no =dept_emp.emp_no  

right join:

关键字会右表  那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。

牛客的在线sq编程l题_第3张图片

https://www.w3school.com.cn/sql/sql_join_right.asp

这个代码加了非空判断,但是一直报返回非零的错误,先记录,学得多了再解决。

select employees.last_name,employees.first_name,dept_emp.dept_no from employees 
right join dept_emp on employees.emp_no =dept_emp.emp_no  
where  employees.last_name and  employees.first_name;

 

OUTER JOIN (外连接)

 

牛客的在线sq编程l题_第4张图片

SELECT * FROM 

TABLE_A A FULL 

OUTER JOIN TABLE_B B ON A.KEY = B.KEY

 

LEFT JOIN EXCLUDING INNER JOIN (左连接 - 内连接)

牛客的在线sq编程l题_第5张图片

SELECT * FROM 

TABLE_A A

LEFT JOIN TABLE_B ON A.KEY = B.KEY WHERE B.KEY IS NULL 

题:

获取所有非manager的员工emp_no
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

select employees.emp_no from employees left join dept_manager 
on employees.emp_no = dept_manager.emp_no where dept_manager.emp_no is null

题:

获取所有员工当前的(dept_manager.to_date='9999-01-01')manager,如果员工是manager的话不显示(也就是如果当前的manager是自己的话结果不显示)。输出结果第一列给出当前员工的emp_no,第二列给出其manager对应的emp_no。
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL, -- '所有的员工编号'
`dept_no` char(4) NOT NULL, -- '部门编号'
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL, -- '部门编号'
`emp_no` int(11) NOT NULL, -- '经理编号'
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

select dept_emp.emp_no ,dept_manager.emp_no 
from dept_emp left join dept_manager
on dept_emp.dept_no = dept_manager.dept_no
where dept_emp.emp_no <> dept_manager.emp_no and dept_manager.to_date='9999-01-01'

RIGHT JOIN EXCLUDING INNER JOIN (右连接 - 内连接)

牛客的在线sq编程l题_第6张图片

SELECT * FROM

TABLE_A A

RIGHT JOIN TABLE_B B ON A.KEY = B.KEY WHERE A.KEY IS NULL

 

OUTER JOIN EXCLUDING INNER JOIN (外连接 - 内连接)

 

牛客的在线sq编程l题_第7张图片

SELECT * FROM 

TABLE_A

FULL OUTER JOIN TABLE_B B ON A.KEY = B.KEY WHERE A.KEY IS NULL OR B.KEY IS NULL

 

group by ..having  条件

GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。

题1:

查找薪水变动超过15次的员工号emp_no以及其对应的变动次数t
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

先按照emp_no 分组,然后使用having  写入筛选条件

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

题2:

找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

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

题:

获取所有部门中当前(dept_emp.to_date = '9999-01-01')员工当前(salaries.to_date='9999-01-01')薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门升序排列。
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
如插入:
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d001','1996-08-03','1997-08-03');

INSERT INTO salaries VALUES(10001,90000,'1986-06-26','1987-06-26');
INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,72527,'1996-08-03','1997-08-03');
INSERT INTO salaries VALUES(10002,72527,'2000-08-02','2001-08-02');
INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,90000,'1996-08-03','1997-08-03');

select dept_emp.dept_no,dept_emp.emp_no,salaries.salary 
from dept_emp left join salaries on dept_emp.emp_no = salaries.emp_no 
where dept_emp.to_date = '9999-01-01' and salaries.to_date='9999-01-01'
GROUP BY dept_emp.dept_no having salaries.salary = max(salaries.salary )

distinct

在表中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值。

关键词 DISTINCT 用于返回唯一不同的值。https://www.w3school.com.cn/sql/sql_distinct.asp

从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。
注意对于重复的emp_no进行忽略(即emp_no重复的title不计算,title对应的数目t不增加)。
CREATE TABLE IF NOT EXISTS `titles` (
`emp_no` int(11) NOT NULL,
`title` varchar(50) NOT NULL,
`from_date` date NOT NULL,
`to_date` date DEFAULT NULL);

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

一些没见过的操作:

emp_no%2=1

查找employees表所有emp_no为奇数,且last_name不为Mary(注意大小写)的员工信息,并按照hire_date逆序排列(题目不能使用mod函数)
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

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

你可能感兴趣的:(mysql)