`
xitongyunwei
  • 浏览: 929558 次
文章分类
社区版块
存档分类
最新评论

java面试题系列8

阅读更多

1、说说你用过那些ajax技术和框架,说说它们的区别

:去掉对web.xml的监视,把jsp提前编辑成Servlet

有富余物理内存的情况,加大tomcat使用的jvm的内存

6. Java web部分

1Tomcat的优化经验

:去掉对web.xml的监视,把jsp提前编辑成Servlet

有富余物理内存的情况,加大tomcat使用的jvm的内存

1HTTP请求的GETPOST方式的区别

:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,servicedestroy方法表达。

62、解释一下什么是servlet;

:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,servicedestroy方法表达。

1、说一说Servlet的生命周期?

:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,servicedestroy方法表达。

Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGetdoPost)等,当服务器决定将实例销毁的时候调用其destroy方法。

web容器加载servlet,生命周期开始。通过调用servletinit()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servletdestroy()方法。

4Servlet的基本架构

public class ServletName extendsHttpServlet {

public void doPost(HttpServletRequestrequest, HttpServletResponse response) throws

ServletException, IOException {

}

public void doGet(HttpServletRequestrequest, HttpServletResponse response) throws

ServletException, IOException {

}

}

3SERVLET APIforward()redirect()的区别?

:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用

sendRedirect()方法。

60、什么情况下调用doGet()doPost()

Jsp页面中的FORM标签里的method属性为get时调用doGet(),为post时调用doPost()

66Request对象的主要方法:

setAttribute(String name,Object):设置名字为namerequest的参数值

getAttribute(String name):返回由name指定的属性值

getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例

getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组

getCharacterEncoding():返回请求中的字符编码方式

getContentLength():返回请求的Body的长度

getHeader(String name):获得HTTP协议定义的文件头信息

getHeaders(String name):返回指定名字的request Header的所有值,结果是一个枚举的实例

getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例

getInputStream():返回请求的输入流,用于获得请求中的数据

getMethod():获得客户端向服务器端传送数据的方法

getParameter(String name):获得客户端传送给服务器端的有name指定的参数值

getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例

getParametervalues(String name):获得有name指定的参数的所有值

getProtocol():获取客户端向服务器端传送数据所依据的协议名称

getQueryString():获得查询字符串

getRequestURI():获取发出请求字符串的客户端地址

getRemoteAddr():获取客户端的IP地址

getRemoteHost():获取客户端的名字

getSession([Boolean create]):返回和请求相关Session

getServerName():获取服务器的名字

getServletPath():获取客户端所请求的脚本文件的路径

getServerPort():获取服务器的端口号

removeAttribute(String name):删除请求中的一个属性

19forwardredirect的区别

forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。

redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。

4request.getAttribute() request.getParameter() 有何区别?

1. jsp有哪些内置对象?作用分别是什么?分别有什么方法?

:JSP共有以下9个内置的对象:

request 用户端请求,此请求会包含来自GET/POST请求的参数

response 网页传回用户端的回应

pageContext 网页的属性是在这里管理

session 与请求有关的会话期

application servlet 正在执行的内容

out 用来传送回应的输出

config servlet的构架部件

page JSP网页本身

exception 针对错误网页,未捕捉的例外

request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, session数据的有用的方法。

response表示HttpServletResponse对象,并提供了几个用于设置送回浏览器的响应的方法(如cookies,头信息等)

out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。

pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。

session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息

applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息

config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。

page表示从该页面产生的一个servlet实例

2. jsp有哪些动作?作用分别是什么?

(这个问题似乎不重要,不明白为何有此题)

:JSP共有以下6种基本动作

jsp:include:在页面被请求的时候引入一个文件。

jsp:useBean:寻找或者实例化一个JavaBean

jsp:setProperty:设置JavaBean的属性。

jsp:getProperty:输出某个JavaBean的属性。

jsp:forward:把请求转到一个新的页面。

jsp:plugin:根据浏览器类型为Java插件生成OBJECTEMBED标记

59JSP的常用指令

isErrorPage(是否能使用Exception对象)isELIgnored(是否忽略表达式)

3. JSP中动态INCLUDE与静态INCLUDE的区别?

答:动态INCLUDEjsp:include动作实现

<jsp:include page=included.jsp flush=true/>它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数静态INCLUDEinclude伪码实现,定不会检查所含文件的变化,适用于包含静态页面<%@ include file=included.htm %>

4、两种跳转方式分别是什么?有什么区别?

(下面的回答严重错误,应该是想问forwardsendRedirect的区别,毕竟出题的人不是专业搞文字艺术的人,可能表达能力并不见得很强,用词不一定精准,加之其自身的技术面也可能存在一些问题,不一定真正将他的意思表达清楚了,严格意思上来讲,一些题目可能根本就无人能答,所以,答题时要掌握主动,只要把自己知道的表达清楚就够了,而不要去推敲原始题目的具体含义是什么,不要一味想着是在答题)

答:有两种,分别为:

<jsp:include page=included.jspflush=true>

<jsp:forward page= nextpage.jsp/>

前者页面不会转向include所指的页面,只是显示该页的结果,主页面还是原来的页面。执行完后还会回来,相当于函数调用。并且可以带参数.后者完全转向新页面,不会再回来。相当于go to 语句。

63、页面间对象传递的方法

requestsessionapplicationcookie

64JSPServlet有哪些相同点和不同点,他们之间的联系是什么?

JSPServlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"servlet"ServletJSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是JavaHTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。

1MVC的各个部分都有那些技术来实现?如何实现?

:MVCModelViewController的简写。Model代表的是应用的业务逻辑(通过JavaBeanEJB组件实现), View是应用的表示面(由JSP页面产生),Controller是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。

68、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?

Public String translate (String str) {

String tempStr = "";

try {

tempStr = new String(str.getBytes("ISO-8859-1"),"GBK");

tempStr = tempStr.trim();

}

catch (Exception e) {

System.err.println(e.getMessage());

}

return tempStr;

}

1.现在输入n个数字,以逗号,分开;然后可选择升或者降序排序;按提交键就在另一页面显示按什么排序,结果为,提供reset

7. 实际项目开发

1、在eclipse中调试时,怎样查看一个变量的值?

在要查看的变量前先设置断点,然后选中变量,右键选debug as-->Java Application,打开debug透视图,这时在Variables窗口中可以看到变量当前的值。

如果是局部变量,也可以在局部变量窗口中查看。

要知道一个方法被调用的方法调用链,可以在方法栈中查看。

2、你们公司使用的代码配置管理工具是什么?

除了说以前使用cvs,现在新项目使用svn了,还简要说一下使用的过程,如果有可能,还说说仓库的概念和如何使用锁之类的细节。

3、你们的项目总金额多少,多少人开发,总共花了多少个月?

像巴巴运动网这种规模的项目,可以说是45个人、开发了45个月,费用则是450万。按每人每月两万收入去计算,就差不多了。

7. 数据库部分

1、用两种方式根据部门号从高到低,工资从低到高列出每个员工的信息。

employee:

eid,ename,salary,deptid;

select* from employee order by deptid desc,salary

2、列出各个部门中工资高于本部门的平均工资的员工数和部门号,并按部门号排序

创建表:

mysql> create table employee921(id int primary keyauto_increment,name varchar(5

0),salary bigint,deptid int);

插入实验数据:

mysql> insert into employee921values(null,'zs',1000,1),(null,'ls',1100,1),(null

,'ww',1100,1),(null,'zl',900,1),(null,'zl',1000,2), (null,'zl',900,2) ,(null,'z

l',1000,2) , (null,'zl',1100,2);

编写sql语句:

()selectavg(salary) from employee921 group by deptid;

()mysql>select employee921.id,employee921.name,employee921.salary,employee921.dep

tid tid from employee921 where salary > (selectavg(salary) from employee921 wheredeptid = tid);

效率低的一个语句,仅供学习参考使用(在group by之后不能使用where,只能使用having,在group by之前可以使用where,即表示对过滤后的结果分组):

mysql> selectemployee921.id,employee921.name,employee921.salary,employee921.dep

tid tid from employee921 where salary > (selectavg(salary) from employee921 group by deptid having deptid = tid);

()selectcount(*) ,tid

from(

selectemployee921.id,employee921.name,employee921.salary,employee921.deptid tid

from employee921

wheresalary >

(selectavg(salary) from employee921 wheredeptid = tid)

)as t

groupby tid ;

另外一种方式:关联查询

select a.ename,a.salary,a.deptid

fromemp a,

(select deptd,avg(salary) avgsal from emp group by deptid ) b

where a.deptid=b.deptid anda.salary>b.avgsal;

1、存储过程与触发器必须讲,经常被面试到?

create procedure insert_Student (_namevarchar(50),_age int ,out _id int)

begin

insertinto student value(null,_name,_age);

selectmax(stuId) into _id from student;

end;

call insert_Student('wfz',23,@id);

select @id;

mysql> create trigger update_StudentBEFORE update on student FOR EACH ROW

-> select *from student;

触发器不允许返回结果

create triggerupdate_Student BEFORE update on student FOR EACH ROW

insertinto student value(null,'zxx',28);

mysql的触发器目前不能对当前表进行操作

create triggerupdate_Student BEFORE update on student FOR EACH ROW

delete fromarticles where id=8;

这个例子不是很好,最好是用删除一个用户时,顺带删除该用户的所有帖子

这里要注意使用OLD.id

触发器用处还是很多的,比如校内网、开心网、Facebook,你发一个日志,自动通知好友,其实就是在增加日志时做一个后触发,再向通知表中写入条目。因为触发器效率高。而UCH没有用触发器,效率和数据处理能力都很低。

存储过程的实验步骤:

mysql>delimiter |

mysql>create procedure insertArticle_Procedure (pTitle varchar(50),pBid int,out

pId int)

-> begin

-> insert into article1value(null,pTitle,pBid);

-> select max(id) into pId fromarticle1;

-> end;

-> |

Query OK, 0rows affected (0.05 sec)

mysql> callinsertArticle_Procedure('传智播客',1,@pid);

-> |

Query OK, 0rows affected (0.00 sec)

mysql>delimiter ;

mysql>select @pid;

+------+

| @pid |

+------+

| 3 |

+------+

1 row in set(0.00 sec)

mysql>select * from article1;

+----+--------------+------+

| id |title | bid |

+----+--------------+------+

| 1 | test| 1 |

| 2 | chuanzhiboke | 1 |

| 3 | 传智播客 | 1 |

+----+--------------+------+

3 rows in set(0.00 sec)

触发器的实验步骤:

create tableboard1(id int primary key auto_increment,name varchar(50),ar

ticleCountint);

create tablearticle1(id int primary key auto_increment,title varchar(50)

,bid intreferences board1(id));

delimiter |

create triggerinsertArticle_Trigger after insert on article1 for each ro

w begin

-> update board1 setarticleCount=articleCount+1 where id= NEW.bid;

-> end;

-> |

delimiter ;

insert intoboard1 value (null,'test',0);

insert intoarticle1 value(null,'test',1);

还有,每插入一个帖子,都希望将版面表中的最后发帖时间,帖子总数字段进行同步更新,用触发器做效率就很高。下次课设计这样一个案例,写触发器时,对于最后发帖时间可能需要用declare方式声明一个变量,或者是用NEW.posttime来生成。

1、数据库三范式是什么?

第一范式(1NF):字段具有原子性,不可再分。所有关系型数据库系统都满足第一范式)

数据库表中的字段都是单一属性的,不可再分。例如,姓名字段,其中的姓和名必须作为一个整体,无法区分哪部分是姓,哪部分是名,如果要区分出姓和名,必须设计成两个独立的字段。

第二范式(2NF):

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。

要求数据库表中的每个实例或行必须可以被惟一地区分。通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主关键字或主键。

第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。

第三范式的要求如下:

满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。

所以第三范式具有如下特征:
1,每一列只有一个值
2
,每一行都能区分。
3
,每一个表都不包含其他表已经包含的非主关键字信息。

例如,帖子表中只能出现发帖人的id,而不能出现发帖人的id,还同时出现发帖人姓名,否则,只要出现同一发帖人id的所有记录,它们中的姓名部分都必须严格保持一致,这就是数据冗余。

1、说出一些数据库优化方面的经验?

PreparedStatement一般来说比Statement性能高:一个sql发给服务器去执行,涉及步骤:语法检查、语义分析,编译,缓存

“inert into user values(1,1,1)”-à二进制

“inert into user values(2,2,2)”-à二进制

“inert into user values(?,?,?)”-à二进制

有外键约束会影响插入和删除性能,如果程序能够保证数据的完整性,那在设计数据库时就去掉外键。(比喻:就好比免检产品,就是为了提高效率,充分相信产品的制造商)

(对于hibernate来说,就应该有一个变化:empleyee->Deptment对象,现在设计时就成了employeeàdeptid

mysql帮助文档子查询章节的最后部分,例如,根据扫描的原理,下面的子查询语句要比第二条关联查询的效率高:

1. selecte.name,e.salary where e.managerid=(select id from employee where name='zxx');

2. selecte.name,e.salary,m.name,m.salary from employees e,employees m where

e.managerid = m.id and m.name='zxx';

表中允许适当冗余,譬如,主题帖的回复数量和最后回复时间等

将姓名和密码单独从用户表中独立出来。这可以是非常好的一对一的案例哟!

sql语句全部大写,特别是列名和表名都大写。特别是sql命令的缓存功能,更加需要统一大小写,sql语句à发给oracle服务器à语法检查和编译成为内部指令à缓存和执行指令。根据缓存的特点,不要拼凑条件,而是用?PreparedStatment

还有索引对查询性能的改进也是值得关注的。

备注:下面是关于性能的讨论举例

4航班 3个城市

m*n

select * from flight,city whereflight.startcityid=city.cityid and city.name='beijing';

m + n

select * from flight where startcityid =(select cityid from city where cityname='beijing');

select flight.id,'beijing',flight.flightTimefrom flight where startcityid = (select cityid from city where cityname='beijing')

2unionunion all有什么不同?

假设我们有一个表Student,包括以下字段与数据:

drop table student;

create table student
(
id int primary key,
name nvarchar2(50) not null,
score number not null
);

insert into student values(1,'Aaron',78);
insert into student values(2,'Bill',76);
insert into student values(3,'Cindy',89);
insert into student values(4,'Damon',90);
insert into student values(5,'Ella',73);
insert into student values(6,'Frado',61);
insert into student values(7,'Gill',99);
insert into student values(8,'Hellen',56);
insert into student values(9,'Ivan',93);
insert into student values(10,'Jay',90);

commit;

UnionUnion All的区别。

select *
from student
where id < 4

union

select *
from student
where id > 2 and id < 6

结果将是

1 Aaron78
2 Bill 76
3 Cindy 89
4 Damon 90
5 Ella 73

如果换成Union All连接两个结果集,则返回结果是:

1 Aaron78
2 Bill 76
3 Cindy 89
3 Cindy 89
4 Damon 90
5 Ella 73

可以看到,UnionUnion All的区别之一在于对重复结果的处理。

  UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
  这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
 而UNION ALL只是简单的将两个结果合并后就返回。这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。
 从效率上说,UNIONALL要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL

3.分页语句

取出sql表中第31到40的记录(以自动增长ID为主键)

sql server方案1:

select top 10 * from twhere id not in (select top 30 id from t order by id ) orde by id

sql server方案2:

select top 10 * from twhere id in (select top 40 id from t order by id) order by id desc

mysql方案:select * from t order by id limit 30,10

oracle方案:select * from (select rownum r,* from t where r<=40) wherer>30

--------------------待整理进去的内容-------------------------------------

pageSize=20;

pageNo = 5;

1.分页技术1(直接利用sql语句进行分页,效率最高和最推荐的)

mysql:sql = "select * from articleslimit " + (pageNo-1)*pageSize + "," + pageSize;

oracle: sql = "select * from " +

"(selectrownum r,* from " +

"(select* from articles order by postime desc)" +

"whererownum<= " + pageNo*pageSize +") tmp " +

"wherer>" + (pageNo-1)*pageSize;

注释:第7行保证rownum的顺序是确定的,因为oracle的索引会造成rownum返回不同的值

简洋提示:没有orderby时,rownum按顺序输出,一旦有了order byrownum不按顺序输出了,这说明rownum是排序前的编号。如果对order by从句中的字段建立了索引,那么,rownum也是按顺序输出的,因为这时候生成原始的查询结果集时会参照索引表的顺序来构建。

sqlserver:sql = "select top 10 * fromid not id(select top " + (pageNo-1)*pageSize + "id fromarticles)"

DataSource ds = newInitialContext().lookup(jndiurl);

Connection cn = ds.getConnection();

//"select * from user whereid=?" --->binary directive

PreparedStatement pstmt =cn.prepareSatement(sql);

ResultSet rs = pstmt.executeQuery()

while(rs.next())

{

out.println(rs.getString(1));

}

2.不可滚动的游标

pageSize=20;

pageNo = 5;

cn = null

stmt = null;

rs = null;

try

{

sqlserver:sql = "select * from articles";

DataSource ds = newInitialContext().lookup(jndiurl);

Connection cn = ds.getConnection();

//"select * from user whereid=?" --->binary directive

PreparedStatement pstmt =cn.prepareSatement(sql);

ResultSet rs = pstmt.executeQuery()

for(int j=0;j<(pageNo-1)*pageSize;j++)

{

rs.next();

}

int i=0;

while(rs.next() && i<10)

{

i++;

out.println(rs.getString(1));

}

}

cacth(){}

finnaly

{

if(rs!=null)try{rs.close();}catch(Exceptione){}

if(stm.........

if(cn............

}

3.可滚动的游标

pageSize=20;

pageNo = 5;

cn = null

stmt = null;

rs = null;

try

{

sqlserver:sql = "select * from articles";

DataSource ds = newInitialContext().lookup(jndiurl);

Connection cn = ds.getConnection();

//"select * from user whereid=?" --->binary directive

PreparedStatement pstmt =cn.prepareSatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,...);

//根据上面这行代码的异常SQLFeatureNotSupportedException,就可判断驱动是否支持可滚动游标

ResultSet rs = pstmt.executeQuery()

rs.absolute((pageNo-1)*pageSize)

int i=0;

while(rs.next() && i<10)

{

i++;

out.println(rs.getString(1));

}

}

cacth(){}

finnaly

{

if(rs!=null)try{rs.close();}catch(Exceptione){}

if(stm.........

if(cn............

}

3.用一条SQL语句查询出每门课都大于80分的学生姓名

name kecheng fenshu
张三语文
81
张三数学
75
李四语文
76
李四数学
90
王五语文
81
王五数学
100
王五英语
90

准备数据的sql代码:

create table score(id int primary key auto_increment,namevarchar(20),subject varchar(20),score int);

insert into score values

(null,'张三','语文',81),

(null,'张三','数学',75),

(null,'李四','语文',76),

(null,'李四','数学',90),

(null,'王五','语文',81),

(null,'王五','数学',100),

(null,'王五 ','英语',90);

提示:当百思不得其解时,请理想思维,把小变成大做,把大变成小做,

答案:
A: select distinct name from score where name not in (selectdistinct name from score where score<=80)

B:select distince name t1 from score where80< all (select score from score where name=t1);

4.所有部门之间的比赛组合

一个叫department的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球对,现在四个球对进行比赛,用一条sql语句显示所有可能的比赛组合.

答:select a.name,b.name
from team a, team b
where a.name < b.name

4.每个月份的发生额都比101科目多的科目

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

准备数据的sql代码:

drop table if exists TestDB;

create table TestDB(id int primary key auto_increment,AccIDvarchar(20), Occmonth date, DebitOccur bigint);

insert into TestDB values

(null,'101','1988-1-1',100),

(null,'101','1988-2-1',110),

(null,'101','1988-3-1',120),

(null,'101','1988-4-1',100),

(null,'101','1988-5-1',100),

(null,'101','1988-6-1',100),

(null,'101','1988-7-1',100),

(null,'101','1988-8-1',100);

--复制上面的数据,故意把第一个月份的发生额数字改小一点

insert into TestDB values

(null,'102','1988-1-1',90),

(null,'102','1988-2-1',110),

(null,'102','1988-3-1',120),

(null,'102','1988-4-1',100),

(null,'102','1988-5-1',100),

(null,'102','1988-6-1',100),

(null,'102','1988-7-1',100),

(null,'102','1988-8-1',100);

--复制最上面的数据,故意把所有发生额数字改大一点

insert into TestDB values

(null,'103','1988-1-1',150),

(null,'103','1988-2-1',160),

(null,'103','1988-3-1',180),

(null,'103','1988-4-1',120),

(null,'103','1988-5-1',120),

(null,'103','1988-6-1',120),

(null,'103','1988-7-1',120),

(null,'103','1988-8-1',120);

--复制最上面的数据,故意把所有发生额数字改大一点

insert into TestDB values

(null,'104','1988-1-1',130),

(null,'104','1988-2-1',130),

(null,'104','1988-3-1',140),

(null,'104','1988-4-1',150),

(null,'104','1988-5-1',160),

(null,'104','1988-6-1',170),

(null,'104','1988-7-1',180),

(null,'104','1988-8-1',140);

--复制最上面的数据,故意把第二个月份的发生额数字改小一点

insert into TestDB values

(null,'105','1988-1-1',100),

(null,'105','1988-2-1',80),

(null,'105','1988-3-1',120),

(null,'105','1988-4-1',100),

(null,'105','1988-5-1',100),

(null,'105','1988-6-1',100),

(null,'105','1988-7-1',100),

(null,'105','1988-8-1',100);

答案:
select distinct AccID from TestDB

where AccID not in

(selectTestDB.AccIDfrom TestDB,

(select * from TestDB where AccID='101') asdb101

where TestDB.Occmonth=db101.Occmonthand TestDB.DebitOccur<=db101.DebitOccur

);

4.统计每年每月的信息

yearmonthamount
1991 1 1.1
1991 2 1.2
1991 3 1.3
1991 4 1.4
1992 1 2.1
1992 2 2.2
1992 3 2.3
1992 4 2.4
查成这样一个结果
year m1m2m3m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4

提示:这个与工资条非常类似,与学生的科目成绩也很相似。

准备sql语句:

drop table if existssales;

create table sales(idint auto_increment primary key,year varchar(10), month varchar(10), amountfloat(2,1));

insert into sales values

(null,'1991','1',1.1),

(null,'1991','2',1.2),

(null,'1991','3',1.3),

(null,'1991','4',1.4),

(null,'1992','1',2.1),

(null,'1992','2',2.2),

(null,'1992','3',2.3),

(null,'1992','4',2.4);


答案一、
select sales.year ,

(select t.amount fromsales t where t.month='1' and t.year= sales.year) '1',

(select t.amount fromsales t where t.month='1' and t.year= sales.year) '2',

(select t.amount fromsales t where t.month='1' and t.year= sales.year) '3',

(select t.amount fromsales t where t.month='1' and t.year= sales.year) as '4'

from sales group by year;

5.显示文章标题,发帖人、最后回复时间

表:id,title,postuser,postdate,parentid

准备sql语句:

drop table if exists articles;

create table articles(id int auto_increment primary key,titlevarchar(50), postuser varchar(10), postdate datetime,parentid int referencesarticles(id));

insert into articles values

(null,'第一条','张三','1998-10-10 12:32:32',null),

(null,'第二条','张三','1998-10-10 12:34:32',null),

(null,'第一条回复1','李四','1998-10-10 12:35:32',1),

(null,'第二条回复1','李四','1998-10-10 12:36:32',2),

(null,'第一条回复2','王五','1998-10-10 12:37:32',1),

(null,'第一条回复3','李四','1998-10-10 12:38:32',1),

(null,'第二条回复2','李四','1998-10-10 12:39:32',2),

(null,'第一条回复4','王五','1998-10-10 12:39:40',1);

答案:

select a.title,a.postuser,

(selectmax(postdate) from articles where parentid=a.id) reply

from articles a where a.parentid is null;

注释:子查询可以用在选择列中,也可用于where的比较条件中,还可以用于from从句中。

3.删除除了id号不同,其他都相同的学生冗余信息

2.学生表如下:
id
学号姓名课程编号课程名称分数
1 2005001 张三0001数学 69
2 2005002
李四0001 数学 89
3 2005001
张三0001 数学 69
A: delete from tablename where id
not in(select min(id) from tablename group by学号,姓名,课程编号,课程名称,分数)

实验:

create table student2(id int auto_incrementprimary key,code varchar(20),name varchar(20));

insert into student2 values(null,'2005001','张三'),(null,'2005002','李四'),(null,'2005001','张三');

//如下语句,mysql报告错误,可能删除依赖后面统计语句,而删除又导致统计语句结果不一致。

delete from student2 where id not in(selectmin(id) from student2 group by name);

//但是,如下语句没有问题:

select * from student2 where id not in(select min(id)from student2 group by name);

//于是,我想先把分组的结果做成虚表,然后从虚表中选出结果,最后再将结果作为删除的条件数据。

delete from student2 where id not in(selectmid from (select min(id) mid

from student2 group by name) as t);

或者:

delete from student2 where id not in(selectmin(id) from (select * from s

tudent2) as t group by t.name);

4.航空网的几个航班查询题:

表结构如下:

flight{flightID,StartCityID,endCityID,StartTime}

city{cityID, CityName)

实验环境:

create table city(cityID int auto_incrementprimary key,cityName varchar(20));

create table flight (flightID intauto_increment primary key,

StartCityIDint references city(cityID),

endCityID int references city(cityID),

StartTimetimestamp);

//航班本来应该没有日期部分才好,但是下面的题目当中涉及到了日期

insert into city values(null,'北京'),(null,'上海'),(null,'广州');

insert into flight values

(null,1,2,'9:37:23'),(null,1,3,'9:37:23'),(null,1,2,'10:37:23'),(null,2,3,'10:37:23');

1、查询起飞城市是北京的所有航班,按到达城市的名字排序

参与运算的列是我起码能够显示出来的那些列,但最终我不一定把它们显示出来。各个表组合出来的中间结果字段中必须包含所有运算的字段。

select * from flight f,city c

wheref.endcityid = c.cityid and startcityid =

(selectc1.cityid from city c1 where c1.cityname = "北京")

orderby c.cityname asc;

mysql> select flight.flightid,'北京' startcity, e.cityname fromflight,city e wh

ere flight.endcityid=e.cityid andflight.startcityid=(select cityid from city wh

ere cityname='北京');

mysql> selectflight.flightid,s.cityname,e.cityname from flight,city s,city e wh

ere flight.startcityid=s.cityid ands.cityname='北京' andflight.endCityId=e.cit

yID order by e.cityName desc;

2、查询北京到上海的所有航班纪录(起飞城市,到达城市,起飞时间,航班号)

selectc1.CityName,c2.CityName,f.StartTime,f.flightID

from city c1,city c2,flight f

where f.StartCityID=c1.cityID

and f.endCityID=c2.cityID

and c1.cityName='北京'

and c2.cityName='上海'

3、查询具体某一天(2005-5-8)的北京到上海的的航班次数

select count(*) from

(select c1.CityName,c2.CityName,f.StartTime,f.flightID

from city c1,city c2,flight f

where f.StartCityID=c1.cityID

and f.endCityID=c2.cityID

and c1.cityName='北京'

and c2.cityName='上海'

and 查帮助获得的某个日期处理函数(startTime) like '2005-5-8%'

mysql中提取日期部分进行比较的示例代码如下:

select * from flight wheredate_format(starttime,'%Y-%m-%d')='1998-01-02'

5.查出比经理薪水还高的员工信息:

Drop table if not exists employees;

create table employees(id int primary keyauto_increment,name varchar(50)

,salaryint,managerid int references employees(id));

insert into employees values (null,' lhm',10000,null),(null,' zxx',15000,1

),(null,'flx',9000,1),(null,'tg',10000,2),(null,'wzg',10000,3);

Wzg大于flx,lhm大于zxx

解题思路:

根据sql语句的查询特点,是逐行进行运算,不可能两行同时参与运算。

涉及了员工薪水和经理薪水,所有,一行记录要同时包含两个薪水,所有想到要把这个表自关联组合一下。

首先要组合出一个包含有各个员工及该员工的经理信息的长记录,譬如,左半部分是员工,右半部分是经理。而迪卡尔积会组合出很多垃圾信息,先去除这些垃圾信息。

select e.* from employees e,employees mwhere e.managerid=m.id and e.sala

ry>m.salary;

6、求出小于45岁的各个老师所带的大于12岁的学生人数

数据库中有3个表 teacher表,student表,tea_stu关系表。
teacher
teaID nameage
student
stuID nameage
teacher_student
teaID stuID
要求用一条sql查询出这样的结果
1.
显示的字段要有老师name, age 每个老师所带的学生人数
2
只列出老师age40以下,学生age12以上的记录

预备知识:

1.sql语句是对每一条记录依次处理,条件为真则执行动作(select,insert,delete,update)

2.只要是迪卡尔积,就会产生“垃圾”信息,所以,只要迪卡尔积了,我们首先就要想到清除“垃圾”信息

实验准备:

drop table if exists tea_stu;

drop table if exists teacher;

drop table if exists student;

create table teacher(teaID int primarykey,name varchar(50),age int);

create table student(stuID int primarykey,name varchar(50),age int);

create table tea_stu(teaID int referencesteacher(teaID),stuID int references student(stuID));

insert into teachervalues(1,'zxx',45), (2,'lhm',25) , (3,'wzg',26) , (4,'tg',27);

insert into studentvalues(1,'wy',11), (2,'dh',25) , (3,'ysq',26) , (4,'mxc',27);

insert into tea_stuvalues(1,1), (1,2), (1,3);

insert into tea_stuvalues(2,2), (2,3), (2,4);

insert into tea_stu values(3,3), (3,4), (3,1);

insert into tea_stuvalues(4,4), (4,1), (4,2) , (4,3);

结果:2à3,3à2,4à3

解题思路:(真实面试答题时,也要写出每个分析步骤,如果纸张不够,就找别人要)

1要会统计分组信息,统计信息放在中间表中:

selectteaid,count(*) from tea_stu group by teaid;

2接着其实应该是筛除掉小于12岁的学生,然后再进行统计,中间表必须与student关联才能得到12岁以下学生和把该学生记录从中间表中剔除,代码是:

selecttea_stu.teaid,count(*) total from student,tea_stu

wherestudent.stuid=tea_stu.stuid and student.age>12 group by tea_stu.teaid

3.接着把上面的结果做成虚表与teacher进行关联,并筛除大于45的老师

selectteacher.teaid,teacher.name,total from teacher ,(select tea_stu.tea

id,count(*) totalfrom student,tea_stu where student.stuid=tea_stu.stuid and stu

dent.age>12 groupby tea_stu.teaid) as tea_stu2 where teacher.teaid=tea_stu2.tea

id andteacher.age<45;

7.求出发帖最多的人:

select authorid,count(*) total fromarticles

group by authorid

having total=

(selectmax(total2) from (select count(*) total2 from articles group by authorid) ast);

select t.authorid,max(t.total) from

select authorid,count(*) total from articlesas t

这条语句不行,因为max只有一列,不能与其他列混淆。

select authorid,count(*) total fromarticles

group by authorid having total=max(total)也不行。

10、一个用户表中有一个积分字段,假如数据库中有100多万个用户,若要在每年第一天凌晨将积分清零,你将考虑什么,你将想什么办法解决?

alter table drop column score;

alter table add colunm score int;

可能会很快,但是需要试验,试验不能拿真实的环境来操刀,并且要注意,

这样的操作时无法回滚的,在我的印象中,只有inert update deleteDML语句才能回滚,

对于createtable,drop table ,alter tableDDL语句是不能回滚。

解决方案一,updateuser set score=0;

解决方案二,假设上面的代码要执行好长时间,超出我们的容忍范围,那我就alter table user drop column score;alter table user add column scoreint

下面代码实现每年的那个凌晨时刻进行清零。

Runnable runnable =

newRunnable(){

publicvoid run(){

clearDb();

schedule(this,newDate(new Date().getYear()+1,0,0));

}

};

schedule(runnable,

newDate(new Date().getYear()+1,0,1));

10、一个用户具有多个角色,请查询出该表中具有该用户的所有角色的其他用户。

select count(*) as num,tb.id

from

tb,

(select role from tb where id=xxx) as t1

where

tb.role= t1.role and tb.id != t1.id

group by tb.id

having

num= select count(role) from tb where id=xxx;

8. xxx公司的sql面试

Table EMPLOYEESStructure:

EMPLOYEE_ID NUMBER Primary Key,

FIRST_NAME VARCHAR2(25),

LAST_NAME VARCHAR2(25),

Salary number(8,2),

HiredDate DATE,

Departmentid number(2)

TableDepartmentsStructure:

Departmentid number(2) PrimaryKey,

DepartmentName VARCHAR2(25).

(2)基于上述EMPLOYEES表写出查询:写出雇用日期在今年的,或者工资在[1000,2000]之间的,或者员工姓名(last_name)以’Obama’打头的所有员工,列出这些员工的全部个人信息。(4分)

select * from employees

where Year(hiredDate) = Year(date())

or(salary between 1000 and 200)

orleft(last_name,3)='abc';

(3) 基于上述EMPLOYEES表写出查询:查出部门平均工资大于1800元的部门的所有员工,列出这些员工的全部个人信息。(4分)

mysql> select id,name,salary,deptid didfrom employee1 where (select avg(salary)

fromemployee1 where deptid = did) > 1800;

(4) 基于上述EMPLOYEES表写出查询:查出个人工资高于其所在部门平均工资的员工,列出这些员工的全部个人信息及该员工工资高出部门平均工资百分比。(5分)

selectemployee1.*,(employee1.salary-t.avgSalary)*100/employee1.salary

from employee1,

(selectdeptid,avg(salary) avgSalary from employee1 group by deptid) as t

where employee1.deptid = t.deptid andemployee1.salary>t.avgSalary;

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics