原始表如下:
第1题,12.2变换结果集成多行
例:你想把行变换成列,需要的结果不止一行,你希望返回每个员工和他们的职位
(此类题型与日历生成类似,日历可以format自动生成用来group by的列,此处只能自己生成,该题还与下方第6题类似)
需要最终结果:
答:
#步骤1:生成rnk列,最最关键
create table x as
select e.job, e.ename, (select count(*) from emp d
where e.job=d.job and e.empno
(精髓是rnk的形成)
步骤1结果:
第2题,12.3反向转换结果集(列变成行)
例:想把列数据变为行数据,分两步
需要最终结果:
第一步结果:
第二步结果:
答:
#步骤1:
create table x as
select sum(case when deptno=10 then 1 else 0 end) as deptno_10,
sum(case when deptno=20 then 1 else 0 end) as deptno_20,
sum(case when deptno=30 then 1 else 0 end) as deptno_30
from emp
#步骤2:
select dept.deptno, case when deptno=10 then x.deptno_10
when deptno=20 then x.deptno_20
when deptno=30 then x.deptno_30
end as count_by_dept
from x, (select distinct deptno from dept where deptno<=30 order by 1) dept
第3题,12.7创建固定大小的数据桶
例:你希望基于EMPNO值为EMP表里的员工分组,一组最多5人(桶的数量不限制,但每个桶最多装5个数据)
需要最终结果:
答:
select ceil(rnk/5) as grp, empno ename
from (select e.empno, e.ename, (select count(*) from emp d where e.empno < d.empno)+1 as rnk
from emp e) x
order by grp
(此处count(*) 必须从0开始,否则要用floor(rnk/5)要出问题的)
第4题,12.8创建预定数目的桶
例:你希望把EMP表中的员工分别放入到4个桶里面(桶的数量一定,里面装多少数据可变)
需要最终结果:
答:
select mod(count(*),4)+1 as grp, e.empno, e.ename
from emp e, emp d
where e.empno>=d.empno
group by e.empno, e.ename
order by 1
第5题,12.9创建水平直方图
例:希望以水平直方图的形式显示每个部门的员工人数,用'*'代表一个员工
需要最终结果:
答:
select deptno, lpad('',count(*),'*') as cnt
from emp
group by deptno
第6题,12.10创建垂直直方图
例:希望以垂直直方图的形式显示每个部门的员工人数,用'*'代表一个员工
需要最终结果:
答:
#步骤1:形成rnk列,最最关键
create table x as
select case when e.deptno=10 then '*' end deptno_10,
case when e.deptno=20 then '*' end deptno_20,
case when e.deptno=30 then '*' end deptno_30,
(select count(*) from emp d where e.deptno=d.deptno and e.empno
(最后的排序,可能不同的数据库不一样,可以升序降序都试一下,按照自己的喜好来)
步骤1结果:
第7题,12.11返回非分组列
例:希望找出每个部门工资最高和最低的员工,同时也找出每个职位对应的工资最高和最低的员工
需要最终结果:
答:
#步骤1:
create table y as
select e.deptno, e.ename, e.job, e.sal,
(select max(sal) from emp d where d.deptno = e.deptno) as maxdept,
(select max(sal) from emp d where d.job = e.job) as maxjob,
(select min(sal) from emp d where d.deptno = e.deptno) as mindept,
(select min(sal) from emp d where d.job = e.job) as minjob
from emp e
#步骤2:
select deptno, ename, job, sal,
case when sal=maxdept then 'top_sal_in_dept'
when sal=mindept then 'low_sal_in_dept'
end as dept_status,
case when sal=maxjob then 'top_sal_in_job'
when sal=minjob then 'low_sal_in_job'
end as dept_status
from y
where sal in (maxdept,mindept,maxjob,minjob)
order by 1
步骤1结果:
第8题,12.12计算简单的小计
例:希望得到一个结果集,既包含了EMP表各个JOB对应的工资合计值,也包括全部工资的总计
需要最终结果:
答:
select coalesce(job,'total') job, sum(sal) sal
from emp
group by job with rollup
第9题,12.17按照时间单位分组
例:你有一些交易日志,希望每隔5秒汇总一下这些数据
生成交易日制表trx_log1:
create table trx_log (TRX_ID int,
TRX_DATE DATETIME(6),
TRX_CNT INT)
insert into trx_log values (1,'2005-07-28 19:03:07',44),
(2,'2005-07-28 19:03:08',18),
(3,'2005-07-28 19:03:09',23),
(4,'2005-07-28 19:03:10',29),
(5,'2005-07-28 19:03:11',27),
(6,'2005-07-28 19:03:12',45),
(7,'2005-07-28 19:03:13',45),
(8,'2005-07-28 19:03:14',32),
(9,'2005-07-28 19:03:15',41),
(10,'2005-07-28 19:03:16',15),
(11,'2005-07-28 19:03:17',24),
(12,'2005-07-28 19:03:18',47),
(13,'2005-07-28 19:03:19',37),
(14,'2005-07-28 19:03:20',48),
(15,'2005-07-28 19:03:21',46),
(16,'2005-07-28 19:03:22',44),
(17,'2005-07-28 19:03:23',36),
(18,'2005-07-28 19:03:24',41),
(19,'2005-07-28 19:03:25',33),
(20,'2005-07-28 19:03:26',19)
create trx_log1 as
select TRX_ID, date_format(TRX_DATE,'%d-%b-%Y %T') as TRX_DATE ,TRX_CNT
from trx_log
交易日制表trx_log1如下图所示:
需要最终结果:
答:
select ceil(trx_id/5)as grp,
min(trx_date) as trx_start,
max(trx_date) as trx_end,
sum(trx_cnt) as total
from trx_log1
group by ceil(trx_id/5)
第10题,12.18多维度聚合运算
例:希望得到一个结果集,包括每个员工的姓名、部门、他所在部门的员工总数(包括他自己)、和他做相同工作的员工总数(包括他自己),以及EMP表中的员工总人数
需要最终结果:
答:
select e.ename,
e.deptno,
(select count(*) from emp d where d.deptno=e.deptno) as deptno_cnt,
job,
(select count(*) from emp d where d.job=e.job) as job_cnt,
(select count(*) from emp ) as total
from emp e
第11题,12.9动态区间聚合运算
例:希望把入职最早的员工的hiredate作为起点,每隔90天计算一次工资合计值。想调查一下,在最早入职的员工和最近入职的员工之间每隔90天工资的波动状况
需要最终结果:
答:
select e.hiredate, e.sal,
(select sum(sal) from emp d
where d.hiredate between e.hiredate-90 and e.hiredate) as spending_pattern
from emp e
order by 1