SQL基础知识整顿
select 查问后果,如: [学号,均匀问题:组函数avg(问题)]from 从哪张表中查找数据,如:[波及到问题:成绩表score]where 查问条件,如:[b.课程号='0003' and b.问题>80]group by 分组,如:[每个学生的均匀:按学号分组](oracle,SQL server中呈现在select 子句后的非分组函数,必须呈现在group by子句后呈现),MySQL中能够不必having 对分组后果指定条件,如:[大于60分]order by 对查问后果排序,如:[增序: 问题 ASC / 降序: 问题 DESC];limit 应用limt子句返回topN(对应这个问题返回的问题前两名),如:[ limit 2 ==>从0索引开始读取2个]limit==>从0索引开始 [0,N-1]
select * from table limit 2,1; -- 含意是跳过2条取出1条数据,limit前面是从第2条开始读,读取1条信息,即读取第3条数据 select * from table limit 2 offset 1; -- 含意是从第1条(不包含)数据开始取出2条数据,limit前面跟的是2条数据,offset前面是从第1条开始读取,即读取第2,3条
组函数: 去重 distinct() 统计总数sum() 计算个数count() 平均数avg() 最大值max() 最小数min()
多表连贯: 内连贯(省略默认inner) join ...on..左连贯left join tableName as b on a.key ==b.key右连贯right join 连贯union(无反复(过滤去重))和union all(有反复[不过滤去重])
- union 并集
- union all(有反复)
- oracle(SQL server)数据库
- intersect 交加
- minus(except) 相减(差集)
oracle
一、数据库对象:表(table) 视图(view) 序列(sequence) 索引(index) 同义词(synonym)
1.视图: 存储起来的 select 语句
create view emp_vwasselect employee_id, last_name, salaryfrom employeeswhere department_id = 90;select * from emp_vw;
能够对简略视图进行 DML 操作
update emp_vwset last_name = 'HelloKitty'where employee_id = 100;select * from employeeswhere employee_id = 100;
1). 简单视图
create view emp_vw2asselect department_id, avg(salary) avg_salfrom employeesgroup by department_id;select * from emp_vw2;
简单视图不能进行 DML 操作
update emp_vw2set avg_sal = 10000where department_id = 100;
2.序列:用于生成一组有法则的数值。(通常用于为主键设置值)
create sequence emp_seq1start with 1increment by 1maxvalue 10000minvalue 1cyclenocache;select emp_seq1.currval from dual;select emp_seq1.nextval from dual;
问题:裂缝,起因:
- 当多个表共用同一个序列时。
- rollback
产生异样
create table emp1( id number(10), name varchar2(30));insert into emp1values(emp_seq1.nextval, '张三');select * from emp1;
3.索引:进步查问效率
主动创立:Oracle 会为具备惟一束缚(惟一束缚,主键束缚)的列,主动创立索引
create table emp2( id number(10) primary key, name varchar2(30))
手动创立
create index emp_idxon emp2(name);create index emp_idx2on emp2(id, name);
4.同义词
create synonym d1 for departments;select * from d1;
5.表:
DDL :数据定义语言 create table .../ drop table ... / rename ... to..../ truncate table.../alter table ...
DML : 数据操纵语言
insert into ... values ...update ... set ... where ...delete from ... where ...
【重要】
select ... 组函数(MIN()/MAX()/SUM()/AVG()/COUNT())from ...join ... on ... 左外连贯:left join ... on ... 右外连贯: right join ... on ...where ...group by ... (oracle,SQL server中呈现在select 子句后的非分组函数,必须呈现在 group by子句后)having ... 用于过滤 组函数order by ... asc 升序, desc 降序limit (0,4) 限度N条数据 如: topN数据- union 并集- union all(有反复)- intersect 交加- minus 相减DCL : 数据管制语言 commit : 提交 / rollback : 回滚 / 受权grant...to... /revoke
索引
何时创立索引:
select employee_id, last_name, salary, department_idfrom employeeswhere department_id in (70, 80) --> 70:1 80:34
- union 并集
- union all(有重复部分)
- intersect 交加
minus 相减
select employee_id, last_name, salary, department_idfrom employeeswhere department_id in (80, 90) --> 90:4 80:34
问题:查问工资大于149号员工工资的员工的信息
select * from employeeswhere salary > ( select salary from employees where employee_id = 149)
问题:查问与141号或174号员工的manager_id和department_id雷同的其余员工的employee_id, manager_id, department_id
select employee_id, manager_id, department_idfrom employeeswhere manager_id in ( select manager_id from employees where employee_id in(141, 174)) and department_id in ( select department_id from employees where employee_id in(141, 174)) and employee_id not in (141, 174);select employee_id, manager_id, department_idfrom employeeswhere (manager_id, department_id) in ( select manager_id, department_id from employees where employee_id in (141, 174)) and employee_id not in(141, 174);
from 子句中应用子查问
select max(avg(salary))from employeesgroup by department_id;select max(avg_sal)from ( select avg(salary) avg_sal from employees group by department_id)
问题:返回比本部门平均工资高的员工的last_name, department_id, salary及平均工资
select last_name, department_id, salary, (select avg(salary) from employees where department_id = e1.department_id)from employees e1where salary > ( select avg(salary) from employees e2 where e1.department_id = e2.department_id)select last_name, e1.department_id, salary, avg_salfrom employees e1, ( select department_id, avg(salary) avg_sal from employees group by department_id) e2where e1.department_id = e2.department_idand e1.salary > e2.avg_sal;case...when ... then... when ... then ... else ... end
查问:若部门为10 查看工资的 1.1 倍,部门号为 20 工资的1.2倍,其余 1.3 倍
SELECT employee_id, last_name, salary,CASEdepartment_id WHEN 10 THENsalary * 1.1 WHEN 20 THENsalary * 1.2 ELSE salary * 1.3 END "new_salary" FROM employees;SELECT employee_id, last_name, salary, decode( department_id, 10, salary * 1.1, 20, salary * 1.2, salary * 1.3 ) "new_salary" FROM employees;
问题:显式员工的employee_id,last_name和location。其中,若员工department_id与location_id为1800的department_id雷同,则location为’Canada’,其余则为’USA’。
select employee_id, last_name, case department_id when ( select department_id from departments where location_id = 1800) then 'Canada' else 'USA' end "location"from employees;
问题:查问员工的employee_id,last_name,要求依照员工的department_name排序
select employee_id, last_namefrom employees e1order by ( select department_name from departments d1 where e1.department_id = d1.department_id)
SQL 优化:能应用 EXISTS 就不要应用 IN
问题:查问公司管理者的employee_id,last_name,job_id,department_id信息
select employee_id, last_name, job_id, department_idfrom employeeswhere employee_id in ( select manager_id from employees)
select employee_id, last_name, job_id, department_idfrom employees e1where exists ( select 'x' from employees e2 where e1.employee_id = e2.manager_id)
问题:查问departments表中,不存在于employees表中的部门的department_id和department_name
select department_id, department_namefrom departments d1where not exists ( select 'x' from employees e1 where e1.department_id = d1.department_id)
更改 108 员工的信息: 使其工资变为所在部门中的最高工资, job 变为公司中平均工资最低的 job
update employees e1set salary = ( select max(salary) from employees e2 where e1.department_id = e2.department_id), job_id = ( select job_id from employees group by job_id having avg(salary) = ( select min(avg(salary)) from employees group by job_id ))where employee_id = 108;
删除 108 号员工所在部门中工资最低的那个员工.
delete from employees e1where salary = ( select min(salary) from employees where department_id = ( select department_id from employees where employee_id = 108 ))select * from employees where employee_id = 108;select * from employees where department_id = 100order by salary;rollback;
常见的SQL面试题:经典50题
已知有如下4张表:
- 学生表:student(学号,学生姓名,出生年月,性别)
- 成绩表:score(学号,课程号,问题)
- 课程表:course(课程号,课程名称,老师号)
- 老师表:teacher(老师号,老师姓名)
依据以上信息依照上面要求写出对应的SQL语句。(搜寻公众号民工哥技术之路,回复“10241”,送你一份技术资源宝典)
ps:这些题考查SQL的编写能力,对于这类型的题目,须要你先把4张表之间的关联关系搞清楚了,最好的方法是本人在草稿纸上画出关联图,而后再编写对应的SQL语句就比拟容易了。下图是我画的这4张表的关系图,能够看出它们之间是通过哪些外键关联起来的:
一、创立数据库和表
为了演示题目的运行过程,咱们先按上面语句在客户端navicat中创立数据库和表。
如何你还不懂什么是数据库,什么是客户端navicat,能够先学习这个:
1.创立表
1)创立学生表(student)
按下图在客户端navicat里创立学生表。举荐:企业面试题汇总
学生表的“学号”列设置为主键束缚,下图是每一列设置的数据类型和束缚
创立完表,点击“保留”
2)创立成绩表(score)
同样的步骤,创立"成绩表“。“课程表的“学号”和“课程号”一起设置为主键束缚(联结主键),“问题”这一列设置为数值类型(float,浮点数值)
3)创立课程表(course)
课程表的“课程号”设置为主键束缚
4)老师表(teacher)
老师表的“老师号”列设置为主键束缚,老师姓名这一列设置束缚为“null”(红框的中央不勾选),示意这一列容许蕴含空值(null)。举荐:企业面试题汇总
向表中增加数据
1)向学生表里增加数据
增加数据的sql
insert into student(学号,姓名,出生日期,性别) values('0001' , '猴子' , '1989-01-01' , '男'); insert into student(学号,姓名,出生日期,性别) values('0002' , '猴子' , '1990-12-21' , '女'); insert into student(学号,姓名,出生日期,性别) values('0003' , '马云' , '1991-12-21' , '男'); insert into student(学号,姓名,出生日期,性别) values('0004' , '王思聪' , '1990-05-20' , '男');
在客户端navicat里的操作
2)成绩表(score)
增加数据的sql
insert into score(学号,课程号,问题) values('0001' , '0001' , 80); insert into score(学号,课程号,问题) values('0001' , '0002' , 90); insert into score(学号,课程号,问题) values('0001' , '0003' , 99); insert into score(学号,课程号,问题) values('0002' , '0002' , 60); insert into score(学号,课程号,问题) values('0002' , '0003' , 80); insert into score(学号,课程号,问题) values('0003' , '0001' , 80); insert into score(学号,课程号,问题) values('0003' , '0002' , 80); insert into score(学号,课程号,问题) values('0003' , '0003' , 80);
客户端navicat里的操作
3)课程表
增加数据的sql
insert into course(课程号,课程名称,老师号)values('0001' , '语文' , '0002'); insert into course(课程号,课程名称,老师号)values('0002' , '数学' , '0001'); insert into course(课程号,课程名称,老师号)values('0003' , '英语' , '0003');
客户端navicat里的操作
4)老师表里增加数据
增加数据的sql
-- 老师表:增加数据insert into teacher(老师号,老师姓名) values('0001' , '孟扎扎'); insert into teacher(老师号,老师姓名) values('0002' , '马化腾'); -- 这里的老师姓名是空值(null)insert into teacher(老师号,老师姓名) values('0003' , null); -- 这里的老师姓名是空字符串('')insert into teacher(老师号,老师姓名) values('0004' , '');
客户端navicat里操作
增加后果
三、50道面试题
为了不便学习,我将50道面试题进行了分类
查问姓“猴”的学生名单
查问姓“孟”老师的个数
select count(老师号)from teacherwhere 老师姓名 like '孟%';
2.汇总统计分组剖析
面试题:查问课程编号为“0002”的总成绩
--剖析思路--select 查问后果 [总成绩:汇总函数sum]--from 从哪张表中查找数据[成绩表score]--where 查问条件 [课程号是0002]select sum(问题)from scorewhere 课程号 = '0002';
查问选了课程的学生人数
--这个题目翻译成大白话就是:查问有多少人选了课程--select 学号,问题表里学号有反复值须要去掉--from 从课程表查找score;select count(distinct 学号) as 学生人数 from score;
查问各科问题最高和最低的分, 以如下的模式显示:课程号,最高分,最低分
/*剖析思路select 查问后果 [课程ID:是课程号的别名,最高分:max(问题) ,最低分:min(问题)]from 从哪张表中查找数据 [成绩表score]where 查问条件 [没有]group by 分组 [各科问题:也就是每门课程的问题,须要按课程号分组];*/select 课程号,max(问题) as 最高分,min(问题) as 最低分from scoregroup by 课程号;
查问每门课程被选修的学生数
/*剖析思路select 查问后果 [课程号,选修该课程的学生数:汇总函数count]from 从哪张表中查找数据 [成绩表score]where 查问条件 [没有]group by 分组 [每门课程:按课程号分组];*/select 课程号, count(学号)from scoregroup by 课程号;
查问男生、女生人数
/*剖析思路select 查问后果 [性别,对应性别的人数:汇总函数count]from 从哪张表中查找数据 [性别在学生表中,所以查找的是学生表student]where 查问条件 [没有]group by 分组 [男生、女生人数:按性别分组]having 对分组后果指定条件 [没有]order by 对查问后果排序[没有];*/select 性别,count(*)from studentgroup by 性别;
查问均匀问题大于60分学生的学号和均匀问题
/* 题目翻译成大白话:均匀问题:开展来说就是计算每个学生的均匀问题这里波及到“每个”就是要分组了均匀问题大于60分,就是对分组后果指定条件剖析思路select 查问后果 [学号,均匀问题:汇总函数avg(问题)]from 从哪张表中查找数据 [问题在成绩表中,所以查找的是成绩表score]where 查问条件 [没有]group by 分组 [均匀问题:先按学号分组,再计算均匀问题]having 对分组后果指定条件 [均匀问题大于60分]*/select 学号, avg(问题)from scoregroup by 学号having avg(问题)>60;
查问至多选修两门课程的学生学号
/* 翻译成大白话:第1步,须要先计算出每个学生选修的课程数据,须要按学号分组第2步,至多选修两门课程:也就是每个学生选修课程数目>=2,对分组后果指定条件剖析思路select 查问后果 [学号,每个学生选修课程数目:汇总函数count]from 从哪张表中查找数据 [课程的学生学号:课程表score]where 查问条件 [至多选修两门课程:须要先计算出每个学生选修了多少门课,须要用分组,所以这里没有where子句]group by 分组 [每个学生选修课程数目:按课程号分组,而后用汇总函数count计算出选修了多少门课]having 对分组后果指定条件 [至多选修两门课程:每个学生选修课程数目>=2]*/select 学号, count(课程号) as 选修课程数目from scoregroup by 学号having count(课程号)>=2;
查问同名同性学生名单并统计同名人数
/* 翻译成大白话,问题解析:1)查找出姓名雷同的学生有谁,每个姓名雷同学生的人数查问后果:姓名,人数条件:怎么算姓名雷同?按姓名分组后人数大于等于2,因为同名的人数大于等于2剖析思路select 查问后果 [姓名,人数:汇总函数count(*)]from 从哪张表中查找数据 [学生表student]where 查问条件 [没有]group by 分组 [姓名雷同:按姓名分组]having 对分组后果指定条件 [姓名雷同:count(*)>=2]order by 对查问后果排序[没有];*/ select 姓名,count(*) as 人数from studentgroup by 姓名having count(*)>=2;
查问不及格的课程并按课程号从大到小排列
/* 剖析思路select 查问后果 [课程号]from 从哪张表中查找数据 [成绩表score]where 查问条件 [不及格:问题 <60]group by 分组 [没有]having 对分组后果指定条件 [没有]order by 对查问后果排序[课程号从大到小排列:降序desc];*/select 课程号from score where 问题<60order by 课程号 desc;
查问每门课程的均匀问题,后果按均匀问题升序排序,均匀问题雷同时,按课程号降序排列
/* 剖析思路select 查问后果 [课程号,均匀问题:汇总函数avg(问题)]from 从哪张表中查找数据 [成绩表score]where 查问条件 [没有]group by 分组 [每门课程:按课程号分组]having 对分组后果指定条件 [没有]order by 对查问后果排序[按均匀问题升序排序:asc,均匀问题雷同时,按课程号降序排列:desc];*/select 课程号, avg(问题) as 均匀问题from scoregroup by 课程号order by 均匀问题 asc,课程号 desc;
检索课程编号为“0004”且分数小于60的学生学号,后果按按分数降序排列
/* 剖析思路select 查问后果 []from 从哪张表中查找数据 [成绩表score]where 查问条件 [课程编号为“04”且分数小于60]group by 分组 [没有]having 对分组后果指定条件 []order by 对查问后果排序[查问后果按按分数降序排列];*/select 学号from scorewhere 课程号='04' and 问题 <60order by 问题 desc;
统计每门课程的学生选修人数(超过2人的课程才统计)
要求输入课程号和选修人数,查问后果按人数降序排序,若人数雷同,按课程号升序排序
/* 剖析思路select 查问后果 [要求输入课程号和选修人数]from 从哪张表中查找数据 []where 查问条件 []group by 分组 [每门课程:按课程号分组]having 对分组后果指定条件 [学生选修人数(超过2人的课程才统计):每门课程学生人数>2]order by 对查问后果排序[查问后果按人数降序排序,若人数雷同,按课程号升序排序];*/select 课程号, count(学号) as '选修人数'from scoregroup by 课程号having count(学号)>2order by count(学号) desc,课程号 asc;
查问两门以上不及格课程的同学的学号及其均匀问题
/*剖析思路先合成题目:1)[两门以上][不及格课程]限度条件2)[同学的学号及其均匀问题],也就是每个学生的均匀问题,显示学号,均匀问题剖析过程:第1步:失去每个学生的均匀问题,显示学号,均匀问题第2步:再加上限度条件:1)不及格课程2)两门以上[不及格课程]:课程数目>2 /* 第1步:失去每个学生的均匀问题,显示学号,均匀问题select 查问后果 [学号,均匀问题:汇总函数avg(问题)]from 从哪张表中查找数据 [波及到问题:成绩表score]where 查问条件 [没有]group by 分组 [每个学生的均匀:按学号分组]having 对分组后果指定条件 [没有]order by 对查问后果排序[没有];*/select 学号, avg(问题) as 均匀问题from scoregroup by 学号; /* 第2步:再加上限度条件:1)不及格课程2)两门以上[不及格课程]select 查问后果 [学号,均匀问题:汇总函数avg(问题)]from 从哪张表中查找数据 [波及到问题:成绩表score]where 查问条件 [限度条件:不及格课程,均匀问题<60]group by 分组 [每个学生的均匀:按学号分组]having 对分组后果指定条件 [限度条件:课程数目>2,汇总函数count(课程号)>2]order by 对查问后果排序[没有];*/select 学号, avg(问题) as 均匀问题from scorewhere 问题 <60group by 学号having count(课程号)>=2;
如果下面题目不会做,能够温习这部分波及到的sql常识:
3.简单查问
查问所有课程问题小于60分学生的学号、姓名
【知识点】子查问
1.翻译成大白话
1)查问后果:学生学号,姓名 2)查问条件:所有课程问题 < 60 的学生,须要从问题表里查找,用到子查问
第1步,写子查问(所有课程问题 < 60 的学生)
select 查问后果[学号]from 从哪张表中查找数据[成绩表:score]where 查问条件[问题 < 60]group by 分组[没有]having 对分组后果指定条件[没有]order by 对查问后果排序[没有]limit 从查问后果中取出指定行[没有];select 学号 from scorewhere 问题 < 60;
第2步,查问后果:学生学号,姓名,条件是后面1步查到的学号
select 查问后果[学号,姓名]from 从哪张表中查找数据[学生表:student]where 查问条件[用到运算符in]group by 分组[没有]having 对分组后果指定条件[没有]order by 对查问后果排序[没有]limit 从查问后果中取出指定行[没有];select 学号,姓名from studentwhere 学号 in (select 学号 from scorewhere 问题 < 60);
查问没有学全所有课的学生的学号、姓名
/*查找出学号,条件:没有学全所有课,也就是该学生选修的课程数 < 总的课程数【考查知识点】in,子查问*/select 学号,姓名from studentwhere 学号 in(select 学号 from scoregroup by 学号having count(课程号) < (select count(课程号) from course));
查问出只选修了两门课程的全副学生的学号和姓名
select 学号,姓名from studentwhere 学号 in(select 学号from scoregroup by 学号having count(课程号)=2);
1990年出世的学生名单
/*查找1990年出世的学生名单学生表中出生日期列的类型是datetime*/select 学号,姓名 from student where year(出生日期)=1990;
查问各科问题前两名的记录
这类问题其实就是常见的:分组取每组最大值、最小值,每组最大的N条(top N)记录。
sql面试题:topN问题
工作中会常常遇到这样的业务问题:
- 如何找到每个类别下用户最喜爱的产品是哪个?
- 如果找到每个类别下用户点击最多的5个商品是什么?
这类问题其实就是常见的:分组取每组最大值、最小值,每组最大的N条(top N)记录。
面对该类问题,如何解决呢?
上面咱们通过成绩表的例子来给出答案。
成绩表是学生的问题,外面有学号(学生的学号),课程号(学生选修课程的课程号),问题(学生选修该课程获得的问题)
分组取每组最大值
案例:按课程号分组取问题最大值所在行的数据
咱们能够应用分组(group by)和汇总函数失去每个组里的一个值(最大值,最小值,平均值等)。然而无奈失去问题最大值所在行的数据。
select 课程号,max(问题) as 最大问题from score group by 课程号;
咱们能够应用关联子查问来实现:
select * from score as a where 问题 = (select max(问题) from score as b where b.课程号 = a.课程号);
下面查问后果课程号“0001”有2行数据,是因为最大问题80有2个
分组取每组最小值
案例:按课程号分组取问题最小值所在行的数据
同样的应用关联子查问来实现
select * from score as a where 问题 = (select min(问题) from score as b where b.课程号 = a.课程号);
每组最大的N条记录
案例:查问各科问题前两名的记录
第1步,查出有哪些组
咱们能够按课程号分组,查问出有哪些组,对应这个问题里就是有哪些课程号
select 课程号,max(问题) as 最大问题from score group by 课程号;
第2步:先应用order by子句按问题降序排序(desc),而后应用limt子句返回topN(对应这个问题返回的问题前两名)
-- 课程号'0001' 这一组里问题前2名select * from score where 课程号 = '0001' order by 问题 desc limit 2;
同样的,能够写出其余组的(其余课程号)取出问题前2名的sql
第3步,应用union all 将每组选出的数据合并到一起
-- 左右滑动能够可拿到全副sql(select * from score where 课程号 = '0001' order by 问题 desc limit 2)union all(select * from score where 课程号 = '0002' order by 问题 desc limit 2)union all(select * from score where 课程号 = '0003' order by 问题 desc limit 2);
后面咱们应用order by子句按某个列降序排序(desc)失去的是每组最大的N个记录。如果想要达到每组最小的N个记录,将order by子句按某个列升序排序(asc)即可。
求topN的问题还能够应用自定义变量来实现,这个在后续再介绍。
如果对多表合并还不理解的,能够看下我讲过的《从零学会SQL》的“多表查问”。
总结
常见面试题:分组取每组最大值、最小值,每组最大的N条(top N)记录。
多表查问
查问所有学生的学号、姓名、选课数、总成绩
select a.学号,a.姓名,count(b.课程号) as 选课数,sum(b.问题) as 总成绩from student as a left join score as bon a.学号 = b.学号group by a.学号;
查问均匀问题大于85的所有学生的学号、姓名和均匀问题
select a.学号,a.姓名, avg(b.问题) as 均匀问题from student as a left join score as bon a.学号 = b.学号group by a.学号having avg(b.问题)>85;
查问学生的选课状况:学号,姓名,课程号,课程名称
select a.学号, a.姓名, c.课程号,c.课程名称from student a inner join score b on a.学号=b.学号inner join course c on b.课程号=c.课程号;
查问出每门课程的及格人数和不及格人数
-- 考查case表达式select 课程号,sum(case when 问题>=60 then 1 else 0 end) as 及格人数,sum(case when 问题 < 60 then 1 else 0 end) as 不及格人数from scoregroup by 课程号;
应用分段[100-85],[85-70],[70-60],[<60]
来统计各科问题,别离统计:各分数段人数,课程号和课程名称
-- 考查case表达式select a.课程号,b.课程名称,sum(case when 问题 between 85 and 100 then 1 else 0 end) as '[100-85]',sum(case when 问题 >=70 and 问题<85 then 1 else 0 end) as '[85-70]',sum(case when 问题>=60 and 问题<70 then 1 else 0 end) as '[70-60]',sum(case when 问题<60 then 1 else 0 end) as '[<60]'from score as a right join course as b on a.课程号=b.课程号group by a.课程号,b.课程名称;
查问课程编号为0003且课程问题在80分以上的学生的学号和姓名|
select a.学号,a.姓名from student as a inner join score as b on a.学号=b.学号where b.课程号='0003' and b.问题>80;
上面是学生的成绩表(表名score,列名:学号、课程号、问题)
应用sql实现将该表行转列为上面的表构造
【面试题类型总结】这类题目属于行列如何调换,解题思路如下:
【面试题】上面是学生的成绩表(表名score,列名:学号、课程号、问题)
应用sql实现将该表行转列为上面的表构造
【解答】
第1步,应用常量列输入指标表的构造
能够看到查问后果曾经和指标表十分靠近了
select 学号,'课程号0001','课程号0002','课程号0003'from score;
第2步,应用case表达式,替换常量列为对应的问题
select 学号,(case 课程号 when '0001' then 问题 else 0 end) as '课程号0001',(case 课程号 when '0002' then 问题 else 0 end) as '课程号0002',(case 课程号 when '0003' then 问题 else 0 end) as '课程号0003'from score;
在这个查问后果中,每一行示意了某个学生某一门课程的问题。比方第一行是'学号0001'选修'课程号00001'的问题,而其余两列的'课程号0002'和'课程号0003'问题为0。
每个学生选修某门课程的问题在下图的每个方块内。咱们能够通过分组,取出每门课程的问题。
第3关,分组
分组,并应用最大值函数max取出上图每个方块里的最大值
select 学号,max(case 课程号 when '0001' then 问题 else 0 end) as '课程号0001',max(case 课程号 when '0002' then 问题 else 0 end) as '课程号0002',max(case 课程号 when '0003' then 问题 else 0 end) as '课程号0003'from scoregroup by 学号;
这样咱们就失去了指标表(行列调换)
作者:sh_c_2450957609
blog.csdn.net/u010565545/article/details/100785261