實例1:測試數據:
create table nba(
team varchar2(20),
year number(4)
)
SQL> select * from nba;
TEAM YEAR
-------------------- -----
活塞 1990
公牛 1991
公牛 1992
公牛 1993
火箭 1994
火箭 1995
公牛 1996
公牛 1997
公牛 1998
馬刺 1999
湖人 2000
湖人 2001
湖人 2002
馬刺 2003
活塞 2004
馬刺 2005
熱火 2006
馬刺 2007
凱爾特人 2008
湖人 2009
湖人 2010
21 rows selected
請寫出一條 SQL 語句,查詢出在此期間連續獲得冠軍的有哪些,其連續的年份的起止時間是多少,結果如下:
TEAM BEGIN END
---------------
公牛 1991 1993
火箭 1994 1995
公牛 1996 1998
湖人 2000 2002
湖人 2009 2010
求解:
SQL> select team, min(t2y), max(t1y)
2 from (select t2.team, t2.year as t2y, t1.year as t1y
3 from nba t1, nba t2
4 where t1.team = t2.team
5 and t1.year = (t2.year + 1)) t
6 group by t.team, (t.t1y - rownum);
TEAM MIN(T2Y) MAX(T1Y)
-------------------- ---------- ----------
公牛 1996 1998
湖人 2009 2010
湖人 2000 2002
公牛 1991 1993
火箭 1994 1995
分析:這個SQL要做的有兩件事:
1)求出連續獲得冠軍的team
2)求出起止年份
關系:根據分析1可知,存在關系team相同的球隊(year=year+1),滿足這個關系的球隊即是連續獲得冠軍的球隊。可以得到SQL如下:
SQL> select t2.team, t2.year as t2y, t1.year as t1y
2 from nba t1, nba t2
3 where t1.team = t2.team
4 and t1.year = (t2.year + 1);
TEAM T2Y T1Y
-------------------- ----- -----
公牛 1991 1992
公牛 1992 1993
火箭 1994 1995
公牛 1996 1997
公牛 1997 1998
湖人 2000 2001
湖人 2001 2002
湖人 2009 2010
8 rows selected
sql中t2y字段表示球隊獲得冠軍每連續兩行之間的最小年份,t1y為連續兩行記錄間的最大年份,最終滿足分析1,和2的結果集到此都可以從這個臨時表中取得了。
下面我們需要對這個臨時表做一個分組,即連續獲得冠軍的球隊我們只需要1行記錄用做顯示,分組字段是什么呢?觀察臨時表結構,這里我們采用(team,t1y-rownum)作為分組條件,這樣連續獲得冠軍的球隊team就可以用一行顯示了。那么我們還差起止年份需要處理一下,就可以出具最終的查詢結果了!從臨時表結構可以看出通過(team,t1y-rownum)分組后,可以由t2y字段我們求出開始年份,即(min(t2y)),可以由t1y字段求出結止年份,即(max(t1y))!繼續處理SQL如下:
SQL> select t.team, min(t2y), max(t1y)
2 from (select t2.team, t2.year as t2y, t1.year as t1y
3 from nba t1, nba t2
4 where t1.team = t2.team
5 and t1.year = (t2.year + 1)) t
6 group by t.team, t1y - rownum
7 order by min(t2y);
TEAM MIN(T2Y) MAX(T1Y)
-------------------- ---------- ----------
公牛 1991 1993
火箭 1994 1995
公牛 1996 1998
湖人 2000 2002
湖人 2009 2010
總結一下,對於這套面試題,對於DBA出身的我,沒有處理過類似問題,如果是我遇到了,估計在紙上是寫不出來,但是自己處理,是可以求出如上結果的。所以寫SQL是一個循序漸進的過程,不是一蹴而就的結果。