SQL中的连续年份计算分析

下表记录了夺冠球队的名称及年份:

请写出一条 SQL 语句,查询出在此期间连续获得冠军的有哪些,其连续的年份的起止时间是多少?

查询结果:

之前我们有讲解如何求解连续多少天的问题,这个题有点类似,但是也有点不一样的地方。
问题分析一般连续性的问题,我们都需要使用笛卡尔积进行错位匹配,就是类似a.ID=b.ID+1的这种。这一题我们也可以使用类似的方法。
具体代码如下:

CREATE TABLE tmp ( ID INT, TEAM VARCHAR ( 20 ), Y INT );
INSERT tmp ( ID, TEAM, Y )
VALUES
    ( 1, '活塞', 1990 ),
    ( 2, '公牛', 1991 ),
    ( 3, '公牛', 1992 ),
    ( 4, '公牛', 1993 ),
    ( 5, '火箭', 1994 ),
    ( 6, '火箭', 1995 ),
    ( 7, '公牛', 1996 ),
    ( 8, '公牛', 1997 ),
    ( 9, '公牛', 1998 ),
    ( 10, '马刺', 1999 ),
    ( 11, '湖人', 2000 ),
    ( 12, '湖人', 2001 ),
    ( 13, '湖人', 2002 ),
    ( 14, '马刺', 2003 ),
    ( 15, '活塞', 2004 ),
    ( 16, '马刺', 2005 ),
    ( 17, '热火', 2006 ),
    ( 18, '马刺', 2007 ),
    ( 19, '凯尔特人', 2008 ),
    ( 20, '湖人', 2009 ),
    ( 21, '湖人', 2010 );
CREATE TABLE tmpx LIKE tmp;

SET @cnt = 0;
INSERT INTO tmpx (
    SELECT
        ( @cnt := @cnt + 1 ) AS ID,
        a.TEAM,
        a.Y 
    FROM
        ( SELECT TEAM, Y FROM tmp GROUP BY TEAM, Y ) a 
    );
--分组排序创建表 
SELECT
a.TEAM,
MIN( a.Y ) B,
MAX( a.Y ) E 
FROM
    tmpx a 
WHERE
    EXISTS (
    SELECT
        1 
    FROM
        tmpx 
    WHERE
        TEAM = a.TEAM 
        AND ( Y = a.Y - 1 OR a.Y = Y - 1 ) 
    ) 
GROUP BY
    a.TEAM,
    Y - ID ;

DROP TABLE tmp,tmpx;

解答的结果如下:

我们对上面的解法进行解读一下:首先是给这些数据添加一列自增长的ID列并插入到新的临时表#a并且对TEAM和Y排序。其次是将#a进行自匹配,匹配的条件是TEAM名称相同(TEAM=a.TEAM),并且年份Y与前后的年份进行匹配(Y=a.Y-1 OR a.Y=Y-1)。这个匹配是精妙地方之一,这样就可以判定该球队前后几年的年份是否连续的。如果球队名相同的前提下,年份连续,就满足这个条件;如果年份连续,但是球队名不相同,就不满足这个条件了。最后在进行分组的时候,不仅对球队TEAM进行了分组,而且还对Y-ID进行了分组。为什么要对Y-ID进行分组呢?如果去掉这个条件,我们发现如下情形:

公牛和湖人中间间隔了几年才重新连续夺冠,但是这里因为没有对Y-ID进行分组,导致这个球队和夺冠年份在进行匹配时都满足了。因为#a表中的内容实际上是这样的,

Y=a.Y-1 OR a.Y=Y-1只要有一个满足即可判断是连续的年份,实际上经过我们处理后确实满足上述条件,所以需要加上Y-ID进行第二次分组来判断中间是否有间隔的年份。因为如果有间隔,那么Y-ID就不是同一个值了。

posted @ 2022-01-25 14:31  渐逝的星光  阅读(291)  评论(0编辑  收藏  举报