MySQL(06)——SQL练习题目(部门员工表)

数据:
把该员工表作为一个自关联表。

-- 部门表
create table dept(
	deptno int primary key auto_increment, -- 部门编号
	dname varchar(14) ,	  -- 部门名字
	loc varchar(13)   -- 地址
) ;
-- 员工表
create table emp(
	empno int primary key auto_increment,-- 员工编号
	ename varchar(10), -- 员工姓名										-
	job varchar(9),	-- 岗位
	mgr int,	 -- 直接领导编号
	hiredate date, -- 雇佣日期,入职日期
	sal int, -- 薪水
	comm int,  -- 提成
	deptno int not null, -- 部门编号
	foreign key (deptno) references dept(deptno)
);
insert into dept values(10,'财务部','北京');
insert into dept values(20,'研发部','上海');
insert into dept values(30,'销售部','广州');
insert into dept values(40,'行政部','深圳');
insert into emp values(7369,'刘一','职员',7902,'1980-12-17',800,null,20);
insert into emp values(7499,'陈二','推销员',7698,'1981-02-20',1600,300,30);
insert into emp values(7521,'张三','推销员',7698,'1981-02-22',1250,500,30);
insert into emp values(7566,'李四','经理',7839,'1981-04-02',2975,null,20);
insert into emp values(7654,'王五','推销员',7698,'1981-09-28',1250,1400,30);
insert into emp values(7698,'赵六','经理',7839,'1981-05-01',2850,null,30);
insert into emp values(7782,'孙七','经理',7839,'1981-06-09',2450,null,10);
insert into emp values(7788,'周八','分析师',7566,'1987-06-13',3000,null,20);
insert into emp values(7839,'吴九','总裁',null,'1981-11-17',5000,null,10);
insert into emp values(7844,'郑十','推销员',7698,'1981-09-08',1500,0,30);
insert into emp values(7876,'郭十一','职员',7788,'1987-06-13',1100,null,20);
insert into emp values(7900,'钱多多','职员',7698,'1981-12-03',950,null,30);
insert into emp values(7902,'大锦鲤','分析师',7566,'1981-12-03',3000,null,20);
insert into emp values(7934,'木有钱','职员',7782,'1983-01-23',1300,null,10);

练习题目:

-- 1.列出至少有一个员工的所有部门。

-- 2.列出薪金比"刘一"多的所有员工。

-- 3.***** 列出所有员工的姓名及其直接上级的姓名。

-- 4.列出受雇日期早于其直接上级的所有员工。

-- 5.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。

-- 6.列出所有job为“职员”的姓名及其部门名称。

-- 7.列出最低薪金大于1500的各种工作。

-- 8.列出在部门 "销售部" 工作的员工的姓名,假定不知道销售部的部门编号。

-- 9.列出薪金高于公司平均薪金的所有员工。

-- 10.列出与"周八"从事相同工作的所有员工。

-- 11.列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金。

-- 12.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。

-- 13.列出在每个部门工作的员工数量、平均工资。

-- 14.列出所有员工的姓名、部门名称和工资。

-- 15.列出所有部门的详细信息和部门人数。

-- 16.列出各种工作的最低工资。

-- 17.列出各个部门的 经理 的最低薪金。

-- 18.列出所有员工的年工资,按年薪从低到高排序。 

-- 19.查出emp表中薪水在3000以上(包括3000)的所有员工的员工号、姓名、薪水。

-- 20.查询出所有薪水在'陈二'之上的所有人员信息。

-- 21.查询出emp表中部门编号为20,薪水在2000以上(不包括2000)的所有员工,显示他们的员工号,姓名以及薪水,以如下列名显示:员工编号 员工名字 薪水

-- 22.查询出emp表中所有的工作种类(无重复)

-- 23.查询出所有奖金(comm)字段不为空的人员的所有信息。

-- 24.查询出薪水在800到2500之间(闭区间)所有员工的信息。(注:使用两种方式实现and以及between and)

-- 25.查询出员工号为7521,7900,7782的所有员工的信息。(注:使用两种方式实现,or以及in)

-- 26.查询出名字中有“张”字符,并且薪水在1000以上(不包括1000)的所有员工信息。

-- 27.查询出名字第三个汉字是“多”的所有员工信息。

-- 28.将所有员工按薪水升序排序,薪水相同的按照入职时间降序排序。

-- 29.将所有员工按照名字首字母升序排序,首字母相同的按照薪水降序排序。 order by convert(name using gbk) asc; 

-- 30.查询出最早工作的那个人的名字、入职时间和薪水。

-- 31.显示所有员工的名字、薪水、奖金,如果没有奖金,暂时显示100.

-- 32.显示出薪水最高人的职位。

-- 33.查出emp表中所有部门的最高薪水和最低薪水,部门编号为10的部门不显示。

-- 34.删除10号部门薪水最高的员工。

-- 35.将薪水最高的员工的薪水降30%。

-- 36.查询员工姓名,工资和 工资级别(工资>=3000 为3级,工资>2000 为2级,工资<=2000 为1级)
-- 语法:case when ... then ... when ... then ... else ... end

sql语句:

-- 1.列出至少有一个员工的所有部门。
select dept.deptno,count(empno) from dept
left outer join emp
on dept.deptno=emp.deptno
group by dept.deptno
having count(empno)>=1
;

-- 2.列出薪金比"刘一"多的所有员工。
-- 2.1 刘一的薪金
select sal from emp where ename='刘一';
-- 2.2 比刘一高的员工
select * from emp where sal>(select sal from emp where ename='刘一');

-- 3.***** 列出所有员工的姓名及其直接上级的姓名。
select e1.ename,e2.ename from emp as e1,emp as e2
where e1.mgr=e2.empno;

-- 4.列出受雇日期早于其直接上级的所有员工。
select e1.ename,e2.ename from emp as e1,emp as e2
where e1.mgr=e2.empno
    and e1.hiredate<e2.hiredate;
;


-- 5.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
select dept.dname,emp.* from dept
left outer join emp
on dept.deptno=emp.deptno;

-- 6.列出所有job为“职员”的姓名及其部门名称。
select emp.ename,dept.dname
from emp,dept
where emp.deptno=dept.deptno
    and emp.job='职员'
;

-- 7.列出最低薪金大于1500的各种工作。
select distinct job
from emp
where sal>1500;

-- 8.列出在部门 "销售部" 工作的员工的姓名,假定不知道销售部的部门编号。
select emp.ename
from emp,dept
where emp.deptno=dept.deptno
    and dept.dname='销售部';


-- 9.列出薪金高于公司平均薪金的所有员工。
select * from emp
where sal>(select avg(sal) from emp);


-- 10.列出与"周八"从事相同工作的所有员工。
-- 周八的工作
select job from emp where ename='周八';

select * from emp
where job = (select job from emp where ename='周八');

-- 方式二 使用exists
select * from emp e1
where exists (select * from emp e2 where e2.job=e1.job and e2.ename='周八' );


-- 11.列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金。
select * from emp
where sal in (select sal from emp where deptno=30);


-- 12.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。
select * from emp
where sal > all(select sal from emp where deptno=30);

-- 13.列出在每个部门工作的员工数量、平均工资。
select dept.deptno,count(emp.empno),avg(sal)
from dept
left outer join emp
on dept.deptno=emp.deptno
group by dept.deptno;

-- 14.列出所有员工的姓名、部门名称和工资。
select emp.ename, dept.dname,emp.sal
from emp, dept
where emp.deptno=dept.deptno;

-- 15.列出所有部门的详细信息和部门人数。
select deptno,count(empno) from emp
group by deptno;

select dept.*, ifnull(empCount,0) as 数量 from dept
left outer join (select deptno,count(empno) as empCount from emp
                    group by deptno) as temp
on dept.deptno=temp.deptno;

-- 16.列出各种工作的最低工资。
select job,min(sal)
from emp
group by job;

-- 17.列出各个部门的 经理 的最低薪金。
select deptno, min(sal)
from emp
where job='经理'
group by deptno;


-- 18.列出所有员工的年工资,按年薪从低到高排序。
select emp.*,(sal+ifnull(comm,0))*12 nianxin from emp
order by nianxin asc
;


-- 19.查出emp表中薪水在3000以上(包括3000)的所有员工的员工号、姓名、薪水。
select empno,ename,sal from emp
where sal>=3000;

-- 20.查询出所有薪水在'陈二'之上的所有人员信息。
select * from emp
where sal>(select sal from emp where ename='陈二');

-- 21.查询出emp表中部门编号为20,薪水在2000以上(不包括2000)的所有员工,
-- 显示他们的员工号,姓名以及薪水,以如下列名显示:员工编号 员工名字 薪水
select empno as 员工编号, ename as 员工名字, sal as 薪水
from emp
where deptno=20
    and sal>2000;

-- 22.查询出emp表中所有的工作种类(无重复)
select distinct job from emp;

-- 23.查询出所有奖金(comm)字段不为空的人员的所有信息。
select * from emp
where comm is not null;

-- 24.查询出薪水在800到2500之间(闭区间)所有员工的信息。(注:使用两种方式实现and以及between and)
select * from emp
where sal >=800 and sal<=2500;

select * from emp
where sal between 800 and 2500;

-- 25.查询出员工号为7521,7900,7782的所有员工的信息。(注:使用两种方式实现,or以及in)
select * from emp
where empno=7521 or empno=7900 or empno=7782;

select * from emp
where empno in (7521, 7900, 7782);

-- 26.查询出名字中有“张”字符,并且薪水在1000以上(不包括1000)的所有员工信息。
select * from emp
where ename like '%张%'
    and sal>1000
;

-- 27.查询出名字第三个汉字是“多”的所有员工信息。
select * from emp
where ename like '__多';

-- 28.将所有员工按薪水升序排序,薪水相同的按照入职时间降序排序。
select * from emp
order by sal asc, hiredate desc;

-- 29.将所有员工按照名字首字母升序排序,首字母相同的按照薪水降序排序。
-- order by convert(name using gbk) asc;
select * from emp
order by convert(substring(ename,1,1) using gbk) asc, sal desc;

-- 30.查询出最早工作的那个人的名字、入职时间和薪水。
select min(hiredate) from emp;

select * from emp
where hiredate = (select min(hiredate) from emp);

-- 31.显示所有员工的名字、薪水、奖金,如果没有奖金,暂时显示100.
select ename,sal,ifnull(comm,100)
from emp;

-- 32.显示出薪水最高人的职位。
select max(sal) from emp;
-- 方式一:
select job from emp
where sal = (select max(sal) from emp);

-- 方式二:
select job from emp
where sal >= all(select sal from emp);

-- 33.查出emp表中所有部门的最高薪水和最低薪水,部门编号为10的部门不显示。
select deptno,max(sal) as maxSal,min(sal) as minSal from emp
group by deptno;

select dept.dname as 部门名称,maxSal 最高薪水,minSal 最低薪水 from dept
left outer join (select deptno,max(sal) as maxSal,min(sal) as minSal from emp
                    group by deptno) temp
on dept.deptno=temp.deptno
where dept.deptno<>10;

-- 34.删除10号部门薪水最高的员工。
select empno from emp
where deptno=10 and sal>=all(select sal from emp where deptno=10);

delete from emp
where empno = (select empno from (select empno from emp
                where deptno=10
                    and sal>=all(select sal from emp where deptno=10))  as temp);

-- 35.将薪水最高的员工的薪水降30%。
select empno from emp
where sal >= all(select sal from emp);

update emp
set sal=sal*(1-0.3)
where empno in (select temp.empno from (select empno from emp
                where sal >= all(select sal from emp)) temp);


select * from emp;

-- 36.查询员工姓名,工资和 工资级别(工资>=3000 为3级,工资>2000 为2级,工资<=2000 为1级)
-- 语法:case when ... then ... when ... then ... else ... end
select ename,
    case when sal>3000 then '3级'
         when sal>2000 then '2级'
         else '1级'
    end
from emp;

<think>好的,我现在需要帮助用户解决关于使用动态规划求解最大全1子矩阵或最大矩形面积的问题。首先,我需要回忆相关知识,并结合用户提供的引用内容来构建回答。 用户引用了三个参考内容。引用[1]提到了使用动态规划处理子矩阵的方法,先计算前缀和,再转换为一维数组的最大子数组问题。引用[2]提到了全1矩阵和极大子矩阵的示例,以及单调和预处理的方法。引用[3]则涉及LeetCode的最大正方形问题,提到了暴力解法和动态规划解法。 用户的需求是动态规划解决最大矩形问题,特别是全1子矩阵或最大面积。我需要将动态规划的方法详细解释清楚,并结合可能的实现步骤。 首先,最大矩形问题通常有两种解法:一种是基于动态规划,另一种是使用单调。但用户明确要求动态规划,所以需要专注于这种方法。不过,根据我的记忆,动态规划在解决最大矩形问题时,通常用于特定情况,比如最大正方形,而对于一般的最大矩形,可能需要结合其他方法,比如使用柱状图的优化,这可能涉及到动态规划预处理。 比如LeetCode中的题目85. 最大矩形,通常的解法是将每一层作为柱状图的底,计算每个位置的高度,然后对每一层使用柱状图中最大矩形算法,而后者可以用单调或者动态规划优化。但用户可能希望的是直接的动态规划解法,或者将动态规划作为预处理步骤。 另一个例子是最大正方形,如引用[3]提到的,动态规划解法是常见的。例如,定义一个dp数组,其中dp[i][j]表示以(i,j)为右下角的最大正方形的边长。状态转移方程是dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1,前提是当前格子为1。 但用户的问题是关于最大矩形面积,而不仅仅是正方形。可能需要结合柱状图的方法,其中动态规划用于计算每一行的高度数组,然后对每个高度数组使用动态规划或单调的方法求解最大矩形面积。 例如,对于每一行,可以维护一个高度数组height,其中height[j]表示当前行第j列向上连续的1的个数。然后,对每一行的height数组,应用柱状图的最大矩形算法,这通常使用单调,但用户可能希望看到动态规划的部分。不过,这里的预处理部分可能涉及动态规划来计算高度数组,而最大矩形部分的计算可能用单调。这时候需要明确回答中如何结合这两个部分。 或者是否存在一种纯动态规划的方法直接解决最大矩形问题?可能需要进一步思考。例如,可能有一种方法记录每个点向左和向上的延伸范围,然后结合这些信息计算最大面积。但这种方法复杂度较高,或者需要更多的状态变量。 根据引用[1]中的方法,用户提到将问题转换为每一行的前缀和,然后对列区间内的行和转换为一维数组的最大子数组,使用动态规划。这可能对应于另一种问题,比如最大子矩阵和,而不是最大全1子矩阵。但用户的问题是关于全1子矩阵,所以可能不适用。不过需要确认是否用户的引用可能有误,或者需要调整思路。 可能用户混淆了最大子矩阵和与最大全1子矩阵的问题,但根据问题描述,用户需要的是全1的情况,即所有元素都是1的最大子矩阵面积。这时候,动态规划的方法可能涉及预处理高度数组,然后对每个高度数组计算最大矩形面积,而这里的动态规划可能是在预处理阶段。 例如,动态规划预处理得到每个位置的高度数组,然后对每个高度数组应用动态规划来求解最大面积。但通常柱状图的最大矩形面积用单调更高效,但用户可能需要动态规划的应用点。 或者是否有动态规划方法直接处理每个高度数组的最大矩形面积?例如,对于每个位置j,在高度数组中,找到左边第一个比height[j]小的位置,和右边第一个比height[j]小的位置,这通常用单调,但若用动态规划的话,可以预处理left和right数组。比如,对于每个j,left[j]表示左边最近的比height[j]小的索引,这可以通过动态规划的方式计算吗? 例如,left数组的每个元素可以递推得到:如果height[j] <= height[j-1],则需要向左查找,直到找到比当前小的。这可能不是典型的动态规划,而是迭代或单调。因此,可能动态规划在此问题中的应用主要是在预处理高度数组,而最大矩形面积的计算可能依赖于其他方法。 因此,在回答用户的问题时,我需要明确动态规划在其中的角色。可能的最大全1子矩阵的动态规划解法包括以下步骤: 1. 预处理高度数组:对于每一行,计算每个位置向上连续的1的数量,这可以通过动态规划逐行处理。例如,如果当前格子是1,则height[i][j] = height[i-1][j] + 1,否则为0。这一步是动态规划。 2. 对每一行的高度数组,计算该行能形成的最大矩形面积。这里通常使用单调的方法,但若用户希望动态规划部分,可能需要转换思路。或者是否有动态规划方法直接处理这部分? 例如,可以针对每个高度数组中的元素,维护两个数组,left和right,分别表示每个位置向左和向右能扩展的最远位置,使得这些位置的高度都不小于当前高度。然后面积就是height[j] * (right[j] - left[j] + 1)。计算left和right数组可以使用动态规划吗? 比如,对于left数组,可以这样递推:对于位置j,如果height[j] > height[j-1],则left[j] = left[j-1],否则需要继续向左找。这可能不完全是动态规划,而更接近迭代的方式。但或许可以将left数组的计算视为动态规划的一种应用,因为每个位置的left值依赖于之前的结果。 或者,另一种思路是,对于每个位置j,在高度数组height中,找到最大的宽度,使得该宽度内的所有高度都>=height[j]。这可能不太容易用动态规划直接解决。 综上,动态规划在解决最大全1子矩阵问题中的主要应用是预处理得到高度数组,而计算最大矩形面积则可能结合其他方法。因此,在回答用户的问题时,需要分步骤解释: - 预处理高度数组的动态规划方法; - 对每一层的高度数组,使用动态规划或其他方法(如单调)计算最大面积; - 综合各层的最大值得到最终结果。 在用户提供的引用中,引用[1]提到了动态规划用于处理一维数组的最大子数组和,这可能与用户的问题不直接相关,但可能用户混淆了问题类型。而引用[3]提到的最大正方形的动态规划解法,可以作为一个子问题来介绍,然后扩展到矩形的情况。 因此,回答的结构可能如下: 1. 动态规划预处理高度数组; 2. 对每行的高度数组应用最大矩形算法(可能结合动态规划或单调); 3. 综合所有行的结果得到最大面积。 此外,用户可能需要具体的实现代码,例如Python代码,来展示动态规划的步骤。 在实现部分,动态规划预处理高度数组的步骤相对明确。例如: 初始化一个height数组,长度与列数相同,初始为0。遍历每一行,如果当前元素是1,则height[j] +=1,否则height[j] =0。这其实是动态规划,因为当前行的height仅依赖于上一行的结果。 然后,对于每一行的height数组,计算最大矩形面积。这里可能需要单调方法,但为了符合用户对动态规划的需求,可能需要寻找另一种方法。或者,可能不存在纯动态规划的方法来计算这一步,这时候需要说明虽然预处理是动态规划,但计算最大矩形面积可能使用其他方法,但这也是整体算法的一部分。 因此,在回答中,需要明确说明动态规划在预处理阶段的作用,然后说明如何利用其他方法(如单调)来处理后续步骤,但整个算法框架可能被视作结合动态规划的方法。 最后,用户可能需要具体的实现示例,例如Python代码。因此,可以提供一个分步骤的代码示例,包括动态规划预处理和单调处理的部分,并解释每个步骤的作用。 现在,整理思路,形成回答: 首先介绍问题:最大全1子矩阵的动态规划解法。 步骤一:动态规划预处理高度数组。对每个位置(i,j),计算从该行向上连续的1的数量。这通过逐行更新height数组实现。 步骤二:对每一行的高度数组,计算当前行能形成的最大矩形面积。这部分使用单调算法,例如类似LeetCode 84题的方法。虽然这部分不是动态规划,但整体算法结合了动态规划的预处理步骤。 步骤三:比较所有行的最大面积,得到全局最大。 然后给出代码示例,展示如何实现上述步骤,并解释关键部分。 同时,根据用户提供的引用,引用[3]提到了最大正方形的动态规划解法,可以对比说明,即最大正方形是最大矩形的一个特例,其中动态规划的状态转移方程不同。 最后,生成相关问题,如动态规划与单调的区别、时间复杂度分析、LeetCode相关题目等。 综上,这样的回答结构应该能够满足用户的需求,结合动态规划和必要的其他方法,同时提供实现代码和相关问题。</think>### 动态规划求解最大全1子矩阵的算法实现 最大全1子矩阵问题要求在一个由0和1组成的二维矩阵中,找到全部由1构成的最大矩形面积。以下是基于动态规划的经典解法,结合预处理和单调优化: --- #### **算法步骤** 1. **预处理高度数组(动态规划)** 逐行遍历矩阵,维护一个数组 `height`,其中 `height[j]` 表示 **当前行第j列向上连续的1的数量**。更新规则为: - 若当前元素为 `'1'`,则 `height[j] += 1`; - 若为 `'0'`,则 `height[j] = 0`。 这一步通过动态规划逐层累积高度,时间复杂度为 $O(mn)$[^3]。 2. **对每行高度数组求最大矩形(单调)** 对每一行的 `height` 数组,使用 **单调** 算法(类似LeetCode 84题)计算当前行的最大矩形面积。具体步骤: - 维护一个单调递增,记录柱状图的索引和高度; - 遍历每个高度时,若当前高度小于顶高度,则弹出顶并计算面积; - 时间复杂度为 $O(n)$ 每行,总复杂度 $O(mn)$[^2]。 3. **全局最大值更新** 记录所有行的最大矩形面积,取全局最大值。 --- #### **Python代码实现** ```python def maximalRectangle(matrix): if not matrix: return 0 max_area = 0 rows, cols = len(matrix), len(matrix[0]) height = [0] * (cols + 1) # 末尾添加0用于触发计算 for row in matrix: # 更新动态规划的高度数组 for j in range(cols): height[j] = height[j] + 1 if row[j] == '1' else 0 # 单调计算当前行的最大矩形 stack = [-1] for k in range(cols + 1): while height[k] < height[stack[-1]]: h = height[stack.pop()] w = k - stack[-1] - 1 max_area = max(max_area, h * w) stack.append(k) return max_area ``` --- #### **关键点解释** - **动态规划预处理**:通过逐行累积高度,将二维问题转化为多个一维柱状图问题。 - **单调优化**:快速找到每个高度能向左右扩展的最大宽度,从而计算面积[^2]。 - **时间复杂度**:总复杂度为 $O(mn)$,适用于大多数实际场景。 --- #### **对比最大正方形问题** 最大正方形是最大矩形的特例,其动态规划状态定义为: $$ dp[i][j] = \min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1 $$ 仅当当前格子为 `'1'` 时更新,记录的是右下角构成的正方形边长。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值