Oracle面试题之:复杂的查询与实例解析 (转发)

当需要对查询到的结果进行比较复杂的处理的时候,可以借助联合查询、子查询等得到期望的结果。下面列举一个具体的经典试题,希望对读者有所启发。

1.题目要求:

表 NBA 记录了TEAM

夺冠球队的名称及年份:

TEAM               YEAR -------------------------------------------------- 活塞                 1990 公牛                 1991 公牛                 1992 公牛                 1993 火箭                 1994 火箭                 1995 公牛                 1996 公牛                 1997 公牛                 1998 马刺                 1999 湖人                 2000 湖人                 2001 湖人                 2002 马刺                 2003 活塞                 2004 马刺                 2005 热火                 2006 马刺                 2007 凯尔特人          2008 湖人                 2009

湖人                 2010


请写出一条 SQL 语句,查询出在此期间连续获得冠军的有哪些,其连续的年份的起止时间是多少,结果如下: TEAM              BEGIN     END ------------------------------------------- 公牛                 1991       1993 火箭                 1994       1995 公牛                 1996       1998 湖人                 2000       2002 湖人                 2009       2010

2.题目分析:

这道题目可以分解为两步:

第一步:找出所有连续获得冠军的球队

第二

 

:计算

 

连续获得冠军的球队的起止年份

3.代码实现

《1》建表并插入一些数据:
 
  1. -- Create table 
  2. create table NBA 
  3.   team NUMBER, 
  4.   year NUMBER 
  5. tablespace USERS 
  6.   pctfree 10 
  7.   initrans 1 
  8.   maxtrans 255 
  9.   storage 
  10.   ( 
  11.     initial 64K 
  12.     minextents 1 
  13.     maxextents unlimited 
  14.   ); 
-- Create table
create table NBA
(
  team NUMBER,
  year NUMBER
)
tablespace USERS
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
为了方便起见,这里仅用数字代替球队,随意插入一些测试数据:
 
《2》我们观察数据发现,如果连续获的一年以上的冠军,那么前一年出现的球队下一年依然会出现,
即:team(year)=team(year+1);
例如下面记录片段 :

活塞                 1990 公牛                 1991 公牛                 1992 公牛                 1993 火箭                 1994

具体的 SQL 语句为:
  1. select n2.team,n2.year  
  2. from (select * from nba) n1   
  3. join 
  4. (select * from nba) n2 
  5. on  
  6. n1.team=n2.team 
  7. where  
  8. n1.year=n2.year+1 
select n2.team,n2.year 
from (select * from nba) n1  
join
(select * from nba) n2
on 
n1.team=n2.team
where 
n1.year=n2.year+1
执行结果为:
 
《3》最后,将上面的查询结果作为子查询,对数据进行处理,因为得冠军最后一年的下面一年不是冠军,
所以结束年份为
  1. max(year)+1: 
max(year)+1:
 
  1. select max(nn.team) team,min(nn.year) BeginYear,max(nn.year)+1 EndYear  
  2. from  
  3. (select n2.team,n2.year from (select * from nba) n1   
  4. join 
  5. (select * from nba) n2 
  6. on  
  7. n1.team=n2.team 
  8. where  
  9. n1.year=n2.year+1) nn 
  10. group by  
  11. (nn.year-rownum) 
  12. order by BeginYear 
select max(nn.team) team,min(nn.year) BeginYear,max(nn.year)+1 EndYear 
from 
(select n2.team,n2.year from (select * from nba) n1  
join
(select * from nba) n2
on 
n1.team=n2.team
where 
n1.year=n2.year+1) nn
group by 
(nn.year-rownum)
order by BeginYear
;
下面是最终的执行结果:
 

4.总结思考

面对类似的面试题目或者问题,虽然涉及的知识点(子查询、连接查询等)不是很多,但是因为有一些数据的转化和查询的嵌套,可能会造成一些心理素质较差的读者手足无措。因此,面对类似的复杂问题,要学会使用“拆分法”进行分解,一步步地解决问题。

       祝你成功!

原文地址:http://blog.csdn.net/sinat_26342009/article/details/45674121

原文地址:https://www.cnblogs.com/xwj517537691/p/4500067.html