SQL中DQL常见面试题

SQL中DQL常见面试题以92语法与99语法的分析

1 常见面试题

/* 
 判断表是否存在的存储过程
*/
declare 
  numb number;
begin
   select count(1) into numb from user_tables where table_name = upper('stu_score');
   if numb>0 then 
     execute immediate 'drop table stu_score';
    end if;
end;

/*
创建表的注释
oracle表示整形浮点都是number,而mysql有double,int,bigint,tinyint,float
*/

create table stu_score(
 stu_name varchar2(30),
 course varchar2(20),
 score number(5,2),
 primary key(stu_name,course)

);
comment on column stu_score.stu_name is '学生姓名';
comment on column stu_score.course is '学生成绩';
comment on column stu_score.course is '学生课程';

insert into stu_score values('张三','语文',78.98);
insert into stu_score values('张三','数学',88.98);
insert into stu_score values('张三','英语',99.98);
insert into stu_score values('李四','语文',98.98);
insert into stu_score values('李四','英语',100);
insert into stu_score values('李四','数学',88.98);
insert into stu_score values('王二','语文',85.98);
insert into stu_score values('王二','数学',84.98);
insert into stu_score values('王二','英语',90.98);
commit;

-- 用一条SQL查询出每门课程都大于80分的学生姓名
select distinct stu_name from stu_score where stu_name not in (select distinct stu_name from stu_score where score<=80);

/*
双引号:双引号的作用:关键字,对象名、字段名加双引号,则示意 Oracle将严格区分大小写,否则Oracl都默认大写。
单引号:一般表示字符串

*/
-- 行列互换1
select stu_name,
  sum(case when course = '语文'then score else 0 end)  "语文",
  sum(case when course = '数学'then score else 0 end)   "数学",
  sum(case when course = '英语'then score else 0 end)  "英语"
from stu_score group by stu_name;

-- 行列互换2
select stu_name,
  sum(decode(course,'语文',score,0)) "语文",
  sum(decode(course,'数学',score,0)) "数学",
  sum(decode(course,'英语',score,0)) "英语"
from stu_score group by stu_name;


-- 2学生表,删除冗余数据
declare 
   n number;
begin 
   select count(1) into n from user_tables where table_name=upper('yp_stu');
   if n>0 then
      execute immediate 'drop table yp_stu';
   end if;
end;

-- 2.1创建学生表
create table yp_stu(
 stu_id number(11) primary key,
 stu_sno number(11) default 0  not null,
 stu_name varchar2(20) default '' not null,
 course varchar2(30) default '' not null,
 score number(5,3) default 0  not null
);

comment on column yp_stu.stu_id is '自增ID';
comment on column yp_stu.stu_sno is '学号';
comment on column yp_stu.stu_name is '姓名';
comment on column yp_stu.score is '分数';
comment on column yp_stu.course is '课程';

-- 2.2 创建自增序列
create sequence stu_id_sequence
increment by 1
start with 1
nomaxvalue
nocycle
cache 20;

-- 2.3插入数据
insert into yp_stu values(stu_id_sequence.nextval,1,'张三','语文',78.9);
insert into yp_stu values(stu_id_sequence.nextval,2,'李四','语文',78.9);
insert into yp_stu values(stu_id_sequence.nextval,1,'张三','语文',78.9);
insert into yp_stu values(stu_id_sequence.nextval,1,'张三','语文',78.9);
commit;

-- 2.4 删除冗余数据
delete  yp_stu where stu_id not in (select min(stu_id) from yp_stu group by stu_sno);
commit;
select * from yp_stu;

-- 3 获取四个球队比赛的所有可能组合
declare 
   n1 number;
begin
   select count(1) into n1 from user_tables where table_name=upper('yp_team');
   if n1>0 then
     execute immediate 'drop table yp_team';
   end if;
end;

-- 创建表
  create table yp_team(
   team_name varchar2(10)
  );
  comment on column yp_team.teamname is '球队的名称';
  insert into yp_team values('a');
  insert into yp_team values('b');
  insert into yp_team values('c');
  insert into yp_team values('d');

select t1.team_name team1,t2.team_name team2 from yp_team t1 ,yp_team t2 where t1.team_name < t2.team_name;


/*
4.
请用SQL 语句实现:从TestDB 数据表中查询出所有月份的发生额都比101 科目相应月份的发生额高的科目。请注意:TestDB 中有很多科目,都有112 月份的发生额。
AccID :科目代码,Occmonth :发生额月份,DebitOccur :发生额。
*/

declare 
  n2 number;
begin 
  select count(1) into n2 from user_tables where table_name=upper('yp_test_db');
  if n2>0 then 
    execute immediate 'drop table yp_test_db';
  end if;
end;

create table yp_test_db(
  acc_id number(11),
  occ_month number(2),
  amount number(7,2)
); 
alter table yp_test_db add constraint test_db_key primary key(acc_id,occ_month);

create sequence test_db_sequence 
increment by 1
start with 1
nocycle
nomaxvalue
cache 20;


insert into yp_test_db  values(test_db_sequence.nextval,1,34.54);
insert into yp_test_db  values(test_db_sequence.currval,2,44.54);
insert into yp_test_db  values(test_db_sequence.currval,3,55.54);
insert into yp_test_db  values(test_db_sequence.currval,4,66.54);
insert into yp_test_db  values(test_db_sequence.currval,5,33.54);
insert into yp_test_db  values(test_db_sequence.currval,6,43.54);
insert into yp_test_db  values(test_db_sequence.currval,7,45.54);
insert into yp_test_db  values(test_db_sequence.currval,8,57.54);
insert into yp_test_db  values(test_db_sequence.currval,9,58.54);
insert into yp_test_db  values(test_db_sequence.currval,10,68.54);
insert into yp_test_db  values(test_db_sequence.currval,11,41.54);
insert into yp_test_db  values(test_db_sequence.currval,12,22.54);

insert into yp_test_db  values(test_db_sequence.nextval,1,74.54);
insert into yp_test_db  values(test_db_sequence.currval,2,84.54);
insert into yp_test_db  values(test_db_sequence.currval,3,55.54);
insert into yp_test_db  values(test_db_sequence.currval,4,66.54);
insert into yp_test_db  values(test_db_sequence.currval,5,33.54);
insert into yp_test_db  values(test_db_sequence.currval,6,93.54);
insert into yp_test_db  values(test_db_sequence.currval,7,65.54);
insert into yp_test_db  values(test_db_sequence.currval,8,57.54);
insert into yp_test_db  values(test_db_sequence.currval,9,58.54);
insert into yp_test_db  values(test_db_sequence.currval,10,68.54);
insert into yp_test_db  values(test_db_sequence.currval,11,71.54);
insert into yp_test_db  values(test_db_sequence.currval,12,62.54);

insert into yp_test_db  values(test_db_sequence.nextval,1,74.54);
insert into yp_test_db  values(test_db_sequence.currval,2,84.54);
insert into yp_test_db  values(test_db_sequence.currval,3,55.54);
insert into yp_test_db  values(test_db_sequence.currval,4,66.54);
insert into yp_test_db  values(test_db_sequence.currval,5,33.54);
insert into yp_test_db  values(test_db_sequence.currval,6,93.54);
insert into yp_test_db  values(test_db_sequence.currval,7,65.54);
insert into yp_test_db  values(test_db_sequence.currval,8,57.54);
insert into yp_test_db  values(test_db_sequence.currval,9,58.54);
insert into yp_test_db  values(test_db_sequence.currval,10,68.54);
insert into yp_test_db  values(test_db_sequence.currval,11,71.54);
insert into yp_test_db  values(test_db_sequence.currval,12,62.54);


insert into yp_test_db  values(test_db_sequence.nextval,1,74.54);
insert into yp_test_db  values(test_db_sequence.currval,2,84.54);
insert into yp_test_db  values(test_db_sequence.currval,3,55.54);
insert into yp_test_db  values(test_db_sequence.currval,4,66.54);
insert into yp_test_db  values(test_db_sequence.currval,5,33.54);
insert into yp_test_db  values(test_db_sequence.currval,6,93.54);
insert into yp_test_db  values(test_db_sequence.currval,7,65.54);
insert into yp_test_db  values(test_db_sequence.currval,8,57.54);
insert into yp_test_db  values(test_db_sequence.currval,9,58.54);
insert into yp_test_db  values(test_db_sequence.currval,10,68.54);
insert into yp_test_db  values(test_db_sequence.currval,11,71.54);
insert into yp_test_db  values(test_db_sequence.currval,12,62.54);

insert into yp_test_db  values(101,1,35.54);
insert into yp_test_db  values(101,2,46.54);
insert into yp_test_db  values(101,3,36.54);
insert into yp_test_db  values(101,4,37.54);
insert into yp_test_db  values(101,5,34.54);
insert into yp_test_db  values(101,6,47.54);
insert into yp_test_db  values(101,7,46.54);
insert into yp_test_db  values(101,8,38.54);
insert into yp_test_db  values(101,9,49.54);
insert into yp_test_db  values(101,10,38.54);
insert into yp_test_db  values(101,11,42.54);
insert into yp_test_db  values(101,12,23.54);

select * from yp_test_db;



-- select tmp1.acc_id, tmp1.month1,tmp1.month2,tmp1.month3,tmp1.month4,tmp1.month5,tmp1.month6,tmp1.month7,tmp1.month8,tmp1.month9,tmp1.month10,tmp1.month11,tmp1.month12 from (


select tmp1.acc_id, tmp1."month1",tmp1."month2",tmp1."month3",tmp1."month4",tmp1."month5",tmp1."month6",tmp1."month7",tmp1."month8",tmp1."month9",tmp1."month10",tmp1."month11",tmp1."month12" from
(
select acc_id,
  sum(decode(occ_month,1,amount,0)) "month1",
   sum(decode(occ_month,2,amount,0)) "month2",
    sum(decode(occ_month,3,amount,0)) "month3",
     sum(decode(occ_month,4,amount,0)) "month4",
      sum(decode(occ_month,5,amount,0)) "month5",
       sum(decode(occ_month,6,amount,0)) "month6",
        sum(decode(occ_month,7,amount,0)) "month7",
         sum(decode(occ_month,8,amount,0)) "month8",
          sum(decode(occ_month,9,amount,0)) "month9",
           sum(decode(occ_month,10,amount,0)) "month10",
            sum(decode(occ_month,11,amount,0)) "month11",
             sum(decode(occ_month,12,amount,0)) "month12"
from yp_test_db group by acc_id) tmp1




select distinct tmp3.* from yp_test_db tmp3, (select acc_id,occ_month,amount from yp_test_db where acc_id=101) tmp2 where tmp3.occ_month=tmp2.occ_month and tmp3.amount<tmp2.amount order by tmp3.acc_id,tmp3.occ_month asc;

-- 6.复制表
drop table b;
create table b
as 
select * from yp_test_db where 1<>1;

-- mysql中
-- 创建表
drop table if exists stu_score;
create table stu_score(
 stu_name varchar(30) comment '学生姓名',
 course varchar(20) comment '课程',
 score double(5,2) comment '成绩',
 primary key(stu_name,course)
);

# 批量插入数据
insert into stu_score 
   values('张三','语文',78.98),
         ('张三','数学',88.98),
         ('张三','英语',99.98),
         ('李四','语文',98.98),
         ('李四','英语',100),
         ('李四','数学',88.98),
         ('王二','语文',85.98),
         ('王二','数学',84.98),
         ('王二','英语',90.98);
# 行列互换1
select stu_name ,
   sum(case when course='语文' then score else 0 end) as "语文",
   sum(case when course='数学' then score else 0 end) as "数学",
   sum(case when course='英语' then score else 0 end) as "英语"
from stu_score group by stu_name;

-- 行列互换2
select stu_name,
  sum(IF(course='语文',score,0)) as "语文",
  sum(IF(course="数学",score,0)) as  "数学",
  sum(IF(course="英语",score,0)) as "英语"
from stu_score group by stu_name;

2 to_char的函数的掌握以及truncate、delete和drop的区别

/*
% 表示零或多个字符
_ 表示一个字符
规定转义字符 escape
*/
select * from emp;
update emp set ename='SMI_TH'where empno=7369;
select * from emp where ename like '%\_%' escape '\';

-- 使用to_char的使用
select to_char(hiredate,'YYYY-MM-DD HH12:MI:SS') from emp
select to_char(sal,'$000,000.00') from emp;

-- 对于null的函数
--  nvl(e1,e2),nvl2(value,e1,e2),decode(value,if,then,if...,else)
select * from emp;
select nvl2(mgr,2,-1) from emp;
-- 对于group by相当于多行函数
-- 如果需要对group by  增加限制条件使用 having
-- 执行顺序 from->where->group by->having->select->order by
select deptno,avg(sal) "avgsal"  from emp group by deptno having avg(sal)>1200;
-- 统计人数小于4的部门的平均工资
select deptno, avg(sal) from emp group by deptno having count(nvl(sal,0))<4;
select count(1),avg(sal) from emp where deptno = 10;

-- 统计各部门的最高工资,排除最高工资小于3000的部门
select deptno,max(sal) from emp group by deptno having max(sal)<3000;

delete from yp_team;

/*
TRUNCATE之后的自增字段从头开始计数了,而DELETE的仍保留原来的最大数值 
1. truncate和 delete只删除数据不删除表的结构(定义) 
    drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态. 
2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发. 
   truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger. 
3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动 
  显然drop语句将表所占用的空间全部释放 
  truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage;   truncate会将高水线复位(回到最开始). 
4.速度,一般来说: drop>; truncate >; delete 
5.安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及
使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大. 
想删除表,当然用drop 
想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete. 
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据 

*/

3 表连接查询的基本方法与特点

3.1 表连接语法的两大类

所谓的92与99语法其实就是1992和1999年归纳出来的语法
92语法:
主要有:笛卡尔集、等值连接、非等值连接、外连接、自连接
99语法:
主要有:交叉连接、自然连接、using、on、外连接

3.2 语法的详细介绍



/*
99与92语法pk
1.交叉连接(cross join)与笛卡儿积结果一样
2.等值连接与using连接结果一样,自然连接条件列只有一列
3.运用left join 和right join 与table1=table2(+)和table1(+)=table2结果一致,只是参照物不一样,
其中,99是以join为参照物,left join 就是左边的表全部展示出来,right join 就是右边的表全部展示出来
92 是以=为参照物,在(+)在右边就是左连接,左边的表数据全部展示出来,而右边没有匹配的就补null,因此个人理解(+)其实有补足的意思。
4.92语法与99语法的区别在于
*/
-- 1.92与99的左连接,右连接类似
select * from dept d,emp e where d.deptno = e.deptno(+);
select * from dept  left join emp using(deptno);

-- 2.92等值连接与99using,以及99自然连接和99的on
select * from dept d,emp e where d.deptno = e.deptno;
select * from dept join emp using(deptno);-- 两张表一定要有同名的字段
select * from dept natural join emp;-- 两张表一定要有同名的字段


select * from dept d join emp e on d.deptno = e.deptno;-- 两张表没有同名字段也可以

-- 总而言之 92等值连接类似与99的自然连接和using连接类似,92非等值连接类似与99的on连接,当然罗,99的on连接也可以连接等值的

-- 3.92的笛卡儿积和99的交叉连接一样
select * from dept ,emp;
select * from dept cross join emp;

/*
总结92语法与99语法的区别
共同点:不管是99语法还是92语法都是实现表连接的,92与99语法都是相同的
区别:1.99语法简化了直观上的过滤条件,把过滤条件单独区分开用on或using实现,或自然连接不用写过滤条件;而92语法如有过滤条件全部都用where实现
      2.对于外连接99拓展了92语法增加了满外连接
*/

猜你喜欢

转载自blog.csdn.net/qq_36226113/article/details/81776368