數據庫部分java
1、用兩種方式根據部門號從高到低,工資從低到高列出每一個員工的信息。mysql
employee:面試
eid,ename,salary,deptid;spring
select * from employee order by deptid desc,salarysql
2、列出各個部門中工資高於本部門的平均工資的員工數和部門號,並按部門號排序數據庫
建立表:緩存
mysql> create table employee921(id int primary key auto_increment,name varchar(5服務器
0),salary bigint,deptid int);oracle
插入實驗數據:框架
mysql> insert into employee921 values(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語句:
()select avg(salary) from employee921 group by deptid;
()mysql> select employee921.id,employee921.name,employee921.salary,employee921.dep
tid tid from employee921 where salary > (select avg(salary) from employee921 where deptid = tid);
效率低的一個語句,僅供學習參考使用(在group by以後不能使用where,只能使用having,在group by以前可使用where,即表示對過濾後的結果分組):
mysql> select employee921.id,employee921.name,employee921.salary,employee921.dep
tid tid from employee921 where salary > (select avg(salary) from employee921 group by deptid having deptid = tid);
()select count(*) ,tid
from (
select employee921.id,employee921.name,employee921.salary,employee921.deptid tid
from employee921
where salary >
(select avg(salary) from employee921 where deptid = tid)
) as t
group by tid ;
另一種方式:關聯查詢
select a.ename,a.salary,a.deptid
from emp a,
(select deptd,avg(salary) avgsal from emp group by deptid ) b
where a.deptid=b.deptid and a.salary>b.avgsal
3、存儲過程與觸發器必須講,常常被面試到?
create procedure insert_Student (_name varchar(50),_age int ,out _id int)
begin
insert into student value(null,_name,_age);
select max(stuId) into _id from student;
end;
call insert_Student('wfz',23,@id);
select @id;
mysql> create trigger update_Student BEFORE update on student FOR EACH ROW
-> select * from student;
觸發器不容許返回結果
create trigger update_Student BEFORE update on student FOR EACH ROW
insert into student value(null,'zxx',28);
mysql的觸發器目前不能對當前表進行操做
create trigger update_Student BEFORE update on student FOR EACH ROW
delete from articles 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 article1 value(null,pTitle,pBid);
-> select max(id) into pId from article1;
-> end;
-> |
Query OK, 0 rows affected (0.05 sec)
mysql> call insertArticle_Procedure('傳智播客',1,@pid);
-> |
Query OK, 0 rows 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 table board1(id int primary key auto_increment,name varchar(50),ar
ticleCount int);
create table article1(id int primary key auto_increment,title varchar(50)
,bid int references board1(id));
delimiter |
create trigger insertArticle_Trigger after insert on article1 for each ro
w begin
-> update board1 set articleCount=articleCount+1 where id= NEW.bid;
-> end;
-> |
delimiter ;
insert into board1 value (null,'test',0);
insert into article1 value(null,'test',1);
還有,每插入一個帖子,都但願將版面表中的最後發帖時間,帖子總數字段進行同步更新,用觸發器作效率就很高。下次課設計這樣一個案例,寫觸發器時,對於最後發帖時間可能須要用declare方式聲明一個變量,或者是用NEW.posttime來生成。
4數據庫三範式是什麼?
第一範式(1NF):字段具備原子性,不可再分。全部關係型數據庫系統都知足第一範式)
數據庫表中的字段都是單一屬性的,不可再分。例如,姓名字段,其中的姓和名必須做爲一個總體,沒法區分哪部分是姓,哪部分是名,若是要區分出姓和名,必須設計成兩個獨立的字段。
第二範式(2NF):
第二範式(2NF)是在第一範式(1NF)的基礎上創建起來的,即知足第二範式(2NF)必須先知足第一範式(1NF)。
要求數據庫表中的每一個實例或行必須能夠被唯一地區分。一般須要爲表加上一個列,以存儲各個實例的唯一標識。這個唯一屬性列被稱爲主關鍵字或主鍵。
第二範式(2NF)要求實體的屬性徹底依賴於主關鍵字。所謂徹底依賴是指不能存在僅依賴主關鍵字一部分的屬性,若是存在,那麼這個屬性和主關鍵字的這一部分應該分離出來造成一個新的實體,新實體與原實體之間是一對多的關係。爲實現區分一般須要爲表加上一個列,以存儲各個實例的唯一標識。簡而言之,第二範式就是非主屬性非部分依賴於主關鍵字。
第三範式的要求以下:
知足第三範式(3NF)必須先知足第二範式(2NF)。簡而言之,第三範式(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字信息。
因此第三範式具備以下特徵: 1,每一列只有一個值 2,每一行都能區分。 3,每個表都不包含其餘表已經包含的非主關鍵字信息。
例如,帖子表中只能出現發帖人的id,而不能出現發帖人的id,還同時出現發帖人姓名,不然,只要出現同一發帖人id的全部記錄,它們中的姓名部分都必須嚴格保持一致,這就是數據冗餘。
5說出一些數據庫優化方面的經驗?
用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. select e.name,e.salary where e.managerid=(select id from employee where name='zxx');
2. select e.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 where flight.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.flightTime from flight where startcityid = (select cityid from city where cityname='beijing')
6、union和union 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;
Union和Union All的區別。
select * from student where id < 4
union
select * from student where id > 2 and id < 6
結果將是
1 Aaron 78 2 Bill 76 3 Cindy 89 4 Damon 90 5 Ella 73
若是換成Union All鏈接兩個結果集,則返回結果是:
1 Aaron 78 2 Bill 76 3 Cindy 89 3 Cindy 89 4 Damon 90 5 Ella 73
能夠看到,Union和Union All的區別之一在於對重複結果的處理。
UNION在進行表連接後會篩選掉重複的記錄,因此在表連接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。實際大部分應用中是不會產生重複的記錄,最多見的是過程表與歷史表UNION。如: select * from gc_dfys union select * from ls_jg_dfys 這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,若是表數據量大的話可能會致使用磁盤進行排序。 而UNION ALL只是簡單的將兩個結果合併後就返回。這樣,若是返回的兩個結果集中有重複的數據,那麼返回的結果集就會包含重複的數據了。 從效率上說,UNION ALL 要比UNION快不少,因此,若是能夠確認合併的兩個結果集中不包含重複的數據的話,那麼就使用UNION ALL,
7.分頁語句
取出sql表中第31到40的記錄(以自動增加ID爲主鍵)
sql server方案1:
select top 10 * from t where id not in (select top 30 id from t order by id ) orde by id
sql server方案2:
select top 10 * from t where 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) where r>30
--------------------待整理進去的內容-------------------------------------
pageSize=20;
pageNo = 5;
1.分頁技術1(直接利用sql語句進行分頁,效率最高和最推薦的)
mysql:sql = "select * from articles limit " + (pageNo-1)*pageSize + "," + pageSize;
oracle: sql = "select * from " +
"(select rownum r,* from " +
"(select * from articles order by postime desc)" +
"where rownum<= " + pageNo*pageSize +") tmp " +
"where r>" + (pageNo-1)*pageSize;
註釋:第7行保證rownum的順序是肯定的,由於oracle的索引會形成rownum返回不一樣的值
簡洋提示:沒有order by時,rownum按順序輸出,一旦有了order by,rownum不按順序輸出了,這說明rownum是排序前的編號。若是對order by從句中的字段創建了索引,那麼,rownum也是按順序輸出的,由於這時候生成原始的查詢結果集時會參照索引表的順序來構建。
sqlserver:sql = "select top 10 * from id not id(select top " + (pageNo-1)*pageSize + "id from articles)"
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?" --->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 = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?" --->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(Exception e){}
if(stm.........
if(cn............
}
3.可滾動的遊標
pageSize=20;
pageNo = 5;
cn = null
stmt = null;
rs = null;
try
{
sqlserver:sql = "select * from articles";
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?" --->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(Exception e){}
if(stm.........
if(cn............
}
8.用一條SQL語句查詢出每門課都大於80分的學生姓名
name kecheng fenshu 張三 語文 81 張三 數學 75 李四 語文 76 李四 數學 90 王五 語文 81 王五 數學 100 王五 英語 90
準備數據的sql代碼:
create table score(id int primary key auto_increment,name varchar(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 (select distinct name from score where score<=80)
B:select distince name t1 from score where 80< all (select score from score where name=t1);
9.全部部門之間的比賽組合
一個叫department的表,裏面只有一個字段name,一共有4條紀錄,分別是a,b,c,d,對應四個球對,如今四個球對進行比賽,用一條sql語句顯示全部可能的比賽組合.
答:select a.name, b.name from team a, team b where a.name < b.name
10.每月份的發生額都比101科目多的科目
請用SQL語句實現:從TestDB數據表中查詢出全部月份的發生額都比101科目相應月份的發生額高的科目。請注意:TestDB中有不少科目,都有1-12月份的發生額。 AccID:科目代碼,Occmonth:發生額月份,DebitOccur:發生額。 數據庫名:JcyAudit,數據集:Select * from TestDB
準備數據的sql代碼:
drop table if exists TestDB;
create table TestDB(id int primary key auto_increment,AccID varchar(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
(select TestDB.AccIDfrom TestDB,
(select * from TestDB where AccID='101') as db101
where TestDB.Occmonth=db101.Occmonth and TestDB.DebitOccur<=db101.DebitOccur
);
11.統計每一年每個月的信息
year month amount 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 m1 m2 m3 m4 1991 1.1 1.2 1.3 1.4 1992 2.1 2.2 2.3 2.4
提示:這個與工資條很是相似,與學生的科目成績也很類似。
準備sql語句:
drop table if exists sales;
create table sales(id int auto_increment primary key,year varchar(10), month varchar(10), amount float(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);
答案1、 select sales.year ,
(select t.amount from sales t where t.month='1' and t.year= sales.year) '1',
(select t.amount from sales t where t.month='1' and t.year= sales.year) '2',
(select t.amount from sales t where t.month='1' and t.year= sales.year) '3',
(select t.amount from sales t where t.month='1' and t.year= sales.year) as '4'
from sales group by year;
12.顯示文章標題,發帖人、最後回覆時間
表:id,title,postuser,postdate,parentid
準備sql語句:
drop table if exists articles;
create table articles(id int auto_increment primary key,title varchar(50), postuser varchar(10), postdate datetime,parentid int references articles(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,
(select max(postdate) from articles where parentid=a.id) reply
from articles a where a.parentid is null;
註釋:子查詢能夠用在選擇列中,也可用於where的比較條件中,還能夠用於from從句中。
13.刪除除了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_increment primary 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(select min(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(select mid from (select min(id) mid
from student2 group by name) as t);
或者:
delete from student2 where id not in(select min(id) from (select * from s
tudent2) as t group by t.name);
14.航空網的幾個航班查詢題:
表結構以下:
flight{flightID,StartCityID ,endCityID,StartTime}
city{cityID, CityName)
實驗環境:
create table city(cityID int auto_increment primary key,cityName varchar(20));
create table flight (flightID int auto_increment primary key,
StartCityID int references city(cityID),
endCityID int references city(cityID),
StartTime timestamp);
//航班原本應該沒有日期部分纔好,可是下面的題目當中涉及到了日期
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');
一、查詢起飛城市是北京的全部航班,按到達城市的名字排序
參與運算的列是我起碼可以顯示出來的那些列,但最終我不必定把它們顯示出來。各個表組合出來的中間結果字段中必須包含全部運算的字段。
select * from flight f,city c
where f.endcityid = c.cityid and startcityid =
(select c1.cityid from city c1 where c1.cityname = "北京")
order by c.cityname asc;
mysql> select flight.flightid,'北京' startcity, e.cityname from flight,city e wh
ere flight.endcityid=e.cityid and flight.startcityid=(select cityid from city wh
ere cityname='北京');
mysql> select flight.flightid,s.cityname,e.cityname from flight,city s,city e wh
ere flight.startcityid=s.cityid and s.cityname='北京' and flight.endCityId=e.cit
yID order by e.cityName desc;
二、查詢北京到上海的全部航班紀錄(起飛城市,到達城市,起飛時間,航班號)
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='上海'
三、查詢具體某一天(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 where date_format(starttime,'%Y-%m-%d')='1998-01-02'
15.查出比經理薪水還高的員工信息:
Drop table if not exists employees;
create table employees(id int primary key auto_increment,name varchar(50)
,salary int,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 m where e.managerid=m.id and e.sala
ry>m.salary;
16、求出小於45歲的各個老師所帶的大於12歲的學生人數
數據庫中有3個表 teacher 表,student表,tea_stu關係表。
teacher 表 teaID name age student 表 stuID name age teacher_student表 teaID stuID 要求用一條sql查詢出這樣的結果
1.顯示的字段要有老師name, age 每一個老師所帶的學生人數 2 只列出老師age爲40如下,學生age爲12以上的記錄
預備知識:
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 primary key,name varchar(50),age int);
create table student(stuID int primary key,name varchar(50),age int);
create table tea_stu(teaID int references teacher(teaID),stuID int references student(stuID));
insert into teacher values(1,'zxx',45), (2,'lhm',25) , (3,'wzg',26) , (4,'tg',27);
insert into student values(1,'wy',11), (2,'dh',25) , (3,'ysq',26) , (4,'mxc',27);
insert into tea_stu values(1,1), (1,2), (1,3);
insert into tea_stu values(2,2), (2,3), (2,4);
insert into tea_stu values(3,3), (3,4), (3,1);
insert into tea_stu values(4,4), (4,1), (4,2) , (4,3);
結果:2à3,3à2,4à3
解題思路:(真實面試答題時,也要寫出每一個分析步驟,若是紙張不夠,就找別人要)
1要會統計分組信息,統計信息放在中間表中:
select teaid,count(*) from tea_stu group by teaid;
2接着其實應該是篩除掉小於12歲的學生,而後再進行統計,中間表必須與student關聯才能獲得12歲如下學生和把該學生記錄從中間表中剔除,代碼是:
select tea_stu.teaid,count(*) total from student,tea_stu
where student.stuid=tea_stu.stuid and student.age>12 group by tea_stu.teaid
3.接着把上面的結果作成虛表與teacher進行關聯,並篩除大於45的老師
select teacher.teaid,teacher.name,total from teacher ,(select tea_stu.tea
id,count(*) total from student,tea_stu where student.stuid=tea_stu.stuid and stu
dent.age>12 group by tea_stu.teaid) as tea_stu2 where teacher.teaid=tea_stu2.tea
id and teacher.age<45;
17.求出發帖最多的人:
select authorid,count(*) total from articles
group by authorid
having total=
(select max(total2) from (select count(*) total2 from articles group by authorid) as t);
select t.authorid,max(t.total) from
(select authorid,count(*) total from articles )as t
這條語句不行,由於max只有一列,不能與其餘列混淆。
select authorid,count(*) total from articles
group by authorid having total=max(total)也不行。
18、一個用戶表中有一個積分字段,假如數據庫中有100多萬個用戶,若要在每一年第一天凌晨將積分清零,你將考慮什麼,你將想什麼辦法解決?
alter table drop column score;
alter table add colunm score int;
可能會很快,可是須要試驗,試驗不能拿真實的環境來操刀,而且要注意,
這樣的操做時沒法回滾的,在個人印象中,只有inert update delete等DML語句才能回滾,
對於create table,drop table ,alter table等DDL語句是不能回滾。
解決方案一,update user set score=0;
解決方案二,假設上面的代碼要執行好長時間,超出咱們的容忍範圍,那我就alter table user drop column score;alter table user add column score int。
下面代碼實現每一年的那個凌晨時刻進行清零。
Runnable runnable =
new Runnable(){
public void run(){
clearDb();
schedule(this,new Date(new Date().getYear()+1,0,0));
}
};
schedule(runnable,
new Date(new Date().getYear()+1,0,1));
1九、一個用戶具備多個角色,請查詢出該表中具備該用戶的全部角色的其餘用戶。
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;
20. xxx公司的sql面試
Table EMPLOYEES Structure:
EMPLOYEE_ID NUMBER Primary Key,
FIRST_NAME VARCHAR2(25),
LAST_NAME VARCHAR2(25),
Salary number(8,2),
HiredDate DATE,
Departmentid number(2)
TableDepartments Structure:
Departmentid number(2) Primary Key,
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)
or left(last_name,3)='abc';
(3) 基於上述EMPLOYEES表寫出查詢:查出部門平均工資大於1800元的部門的全部員工,列出這些員工的所有我的信息。(4分)
mysql> select id,name,salary,deptid did from employee1 where (select avg(salary)
from employee1 where deptid = did) > 1800;
(4) 基於上述EMPLOYEES表寫出查詢:查出我的工資高於其所在部門平均工資的員工,列出這些員工的所有我的信息及該員工工資高出部門平均工資百分比。(5分)
select employee1.*,(employee1.salary-t.avgSalary)*100/employee1.salary
from employee1,
(select deptid,avg(salary) avgSalary from employee1 group by deptid) as t
where employee1.deptid = t.deptid and employee1.salary>t.avgSalary;
21、註冊Jdbc驅動程序的三種方式
22、用JDBC如何調用存儲過程
代碼以下:
package com.huawei.interview.lym;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;
public class JdbcTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Connection cn = null;
CallableStatement cstmt = null;
try {
//這裏最好不要這麼幹,由於驅動名寫死在程序中了
Class.forName("com.mysql.jdbc.Driver");
//實際項目中,這裏應用DataSource數據,若是用框架,
//這個數據源不須要咱們編碼建立,咱們只需Datasource ds = context.lookup()
//cn = ds.getConnection();
cn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
cstmt = cn.prepareCall("{call insert_Student(?,?,?)}");
cstmt.registerOutParameter(3,Types.INTEGER);
cstmt.setString(1, "wangwu");
cstmt.setInt(2, 25);
cstmt.execute();
//get第幾個,不一樣的數據庫不同,建議不寫
System.out.println(cstmt.getString(3));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
/*try{cstmt.close();}catch(Exception e){}
try{cn.close();}catch(Exception e){}*/
try {
if(cstmt != null)
cstmt.close();
if(cn != null)
cn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
23、JDBC中的PreparedStatement相比Statement的好處
答:一個sql命令發給服務器去執行的步驟爲:語法檢查,語義分析,編譯成內部指令,緩存指令,執行指令等過程。
select * from student where id =3----緩存--àxxxxx二進制命令
select * from student where id =3----直接取-àxxxxx二進制命令
select * from student where id =4--- -à會怎麼幹?
若是當初是select * from student where id =?--- -à又會怎麼幹?
上面說的是性能提升
能夠防止sql注入。
24. 寫一個用jdbc鏈接並訪問oracle數據的程序代碼
25、Class.forName的做用?爲何要用?
答:按參數中指定的字符串形式的類名去搜索並加載相應的類,若是該類字節碼已經被加載過,則返回表明該字節碼的Class實例對象,不然,按類加載器的委託機制去搜索和加載該類,若是全部的類加載器都沒法加載到該類,則拋出ClassNotFoundException。加載完這個Class字節碼後,接着就可使用Class字節碼的newInstance方法去建立該類的實例對象了。
有時候,咱們程序中全部使用的具體類名在設計時(即開發時)沒法肯定,只有程序運行時才能肯定,這時候就須要使用Class.forName去動態加載該類,這個類名一般是在配置文件中配置的,例如,spring的ioc中每次依賴注入的具體類就是這樣配置的,jdbc的驅動類名一般也是經過配置文件來配置的,以便在產品交付使用後不用修改源程序就能夠更換驅動類名。
26、大數據量下的分頁解決方法。
答:最好的辦法是利用sql語句進行分頁,這樣每次查詢出的結果集中就只包含某頁的數據內容。再sql語句沒法實現分頁的狀況下,能夠考慮對大的結果集經過遊標定位方式來獲取某頁的數據。
sql語句分頁,不一樣的數據庫下的分頁方案各不同,下面是主流的三種數據庫的分頁sql:
sql server:
String sql =
"select top " + pageSize + " * from students where id not in" +
"(select top " + pageSize * (pageNumber-1) + " id from students order by id)" +
"order by id";
mysql:
String sql =
"select * from students order by id limit " + pageSize*(pageNumber-1) + "," + pageSize;
oracle:
String sql =
27、說出數據鏈接池的工做機制是什麼?
J2EE服務器啓動時會創建必定數量的池鏈接,並一直維持很多於此數目的池鏈接。客戶端程序須要鏈接時,池驅動程序會返回一個未使用的池鏈接並將其表記爲忙。若是當前沒有空閒鏈接,池驅動程序就新建必定數量的鏈接,新建鏈接的數量有配置參數決定。當使用的池鏈接調用完成後,池驅動程序將此鏈接表記爲空閒,其餘調用就可使用這個鏈接。
實現方式,返回的Connection是原始Connection的代理,代理Connection的close方法不是真正關鏈接,而是把它代理的Connection對象還回到鏈接池中。
28、爲何要用 ORM? 和 JDBC 有何不同?
orm是一種思想,就是把object轉變成數據庫中的記錄,或者把數據庫中的記錄轉變成objecdt,咱們能夠用jdbc來實現這種思想,其實,若是咱們的項目是嚴格按照oop方式編寫的話,咱們的jdbc程序無論是有意仍是無心,就已經在實現orm的工做了。
如今有許多orm工具,它們底層調用jdbc來實現了orm工做,咱們直接使用這些工具,就省去了直接使用jdbc的繁瑣細節,提升了開發效率,如今用的較多的orm工具是hibernate。也據說一些其餘orm工具,如toplink,ojb等。