SQL如何求解連續(xù)年份的問題?
本文轉(zhuǎn)載自微信公眾號「SQL數(shù)據(jù)庫開發(fā)」,作者丶平凡世界。轉(zhuǎn)載本文請聯(lián)系SQL數(shù)據(jù)庫開發(fā)公眾號。
最近看到這樣一道題目,覺得挺有意思,給小伙伴們分享一下解題思路。
下表記錄了奪冠球隊(duì)的名稱及年份:
請寫出一條 SQL 語句,查詢出在此期間連續(xù)獲得冠軍的有哪些,其連續(xù)的年份的起止時(shí)間是多少?
查詢結(jié)果:
之前我們有講解如何求解連續(xù)多少天的問題,這個(gè)題有點(diǎn)類似,但是也有點(diǎn)不一樣的地方。
問題分析
一般連續(xù)性的問題,我們都需要使用笛卡爾積進(jìn)行錯(cuò)位匹配,就是類似a.ID=b.ID+1的這種。這一題我們也可以使用類似的方法。
具體代碼如下:
- CREATE TABLE #t(TEAM varchar(20), Y int)
- INSERT #t(TEAM,Y) VALUES
- ('活塞',1990),
- ('公牛',1991),
- ('公牛',1992),
- ('公牛',1993),
- ('火箭',1994),
- ('火箭',1995),
- ('公牛',1996),
- ('公牛',1997),
- ('公牛',1998),
- ('馬刺',1999),
- ('湖人',2000),
- ('湖人',2001),
- ('湖人',2002),
- ('馬刺',2003),
- ('活塞',2004),
- ('馬刺',2005),
- ('熱火',2006),
- ('馬刺',2007),
- ('凱爾特人',2008),
- ('湖人',2009),
- ('湖人',2010);
- SELECT RN=IDENTITY(INT),* INTO #a FROM #t ORDER BY TEAM,Y
- SELECT a.TEAM,
- MIN(a.Y) B,
- MAX(a.Y) E
- FROM #a a
- WHERE EXISTS(
- SELECT 1 FROM #a
- WHERE TEAM=a.TEAM
- AND (Y=a.Y-1 OR a.Y=Y-1)
- )
- GROUP BY a.TEAM,Y-RN
- DROP TABLE #t,#a
解答的結(jié)果如下:
我們對上面的解法進(jìn)行解讀一下:
首先是給這些數(shù)據(jù)添加一列自增長的RN列并插入到新的臨時(shí)表#a并且對TEAM和Y排序。
其次是將#a進(jìn)行自匹配,匹配的條件是TEAM名稱相同(TEAM=a.TEAM),并且年份Y與前后的年份進(jìn)行匹配(Y=a.Y-1 OR a.Y=Y-1)。
這個(gè)匹配是精妙地方之一,這樣就可以判定該球隊(duì)前后幾年的年份是否連續(xù)的。
如果球隊(duì)名相同的前提下,年份連續(xù),就滿足這個(gè)條件;
如果年份連續(xù),但是球隊(duì)名不相同,就不滿足這個(gè)條件了。
最后在進(jìn)行分組的時(shí)候,不僅對球隊(duì)TEAM進(jìn)行了分組,而且還對Y-RN進(jìn)行了分組。為什么要對Y-RN進(jìn)行分組呢?
如果去掉這個(gè)條件,我們發(fā)現(xiàn)如下情形:
公牛和湖人中間間隔了幾年才重新連續(xù)奪冠,但是這里因?yàn)闆]有對Y-RN進(jìn)行分組,導(dǎo)致這個(gè)球隊(duì)和奪冠年份在進(jìn)行匹配時(shí)都滿足了。因?yàn)?a表中的內(nèi)容實(shí)際上是這樣的,
Y=a.Y-1 OR a.Y=Y-1只要有一個(gè)滿足即可判斷是連續(xù)的年份,實(shí)際上經(jīng)過我們處理后確實(shí)滿足上述條件,所以需要加上Y-RN進(jìn)行第二次分組來判斷中間是否有間隔的年份。因?yàn)槿绻虚g隔,那么Y-RN就不是同一個(gè)值了。