T_SQL又另外两种找出3年连续获奖的人
此题目要求查找连续三年获奖的人。首先创建一个表,填充数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ; WITH Prize( Name , Year ) AS ( SELECT 'Kim' , 2001 UNION ALL SELECT 'Tim' , 2002 UNION ALL SELECT 'Tang' , 2002 UNION ALL SELECT 'Jack' , 2001 UNION ALL SELECT 'Juicy' , 2001 UNION ALL SELECT 'Peff' , 2002 UNION All SELECT 'Juicy' , 2002 UNION ALL SELECT 'Kim' , 2002 UNION ALL SELECT 'Juicy' , 2003 UNION ALL SELECT 'Peff' , 2003 UNION ALL SELECT 'Kim' , 2003 UNION ALL SELECT 'Tim' , 2004 UNION ALL SELECT 'Juicy' , 2004 UNION ALL SELECT 'Jack' , 2005 UNION ALL SELECT 'Eric' , 2005 UNION ALL SELECT 'Tim' , 2005 UNION ALL SELECT 'Eric' , 2006 UNION ALL SELECT 'Peff' , 2006 UNION ALL SELECT 'Juicy' , 2007 UNION ALL SELECT 'Eric' , 2007 UNION ALL SELECT 'Tang' , 2007 UNION ALL SELECT 'Tang' , 2008 UNION ALL SELECT 'Peff' , 2008 UNION ALL SELECT 'Kim' , 2008 UNION ALL SELECT 'Jack' , 2009 UNION ALL SELECT 'Tang' , 2009 UNION ALL SELECT 'Kim' , 2009) SELECT * INTO dbo.Prize FROM Prize ORDER BY Name , Year CREATE CLUSTERED INDEX cluster_index_main ON dbo.Prize( Name ) |
Prize表的列Name表示姓名,而year表示获奖的年份。
1 第一种方式:使用T_SQL里面的关键字apply。
Apply有两个输入参数,左边输入和右边输入,右边输入可以为函数,也可以为子查询。对于左边输入的每一行,都会在右输入中进行计算,然后把结果汇总。
那么对于Prize中每一行,我可以把它作为CROSS APPLY的左输入,然后去右输入中查找姓名相等,获奖年份大,但是获奖年份在3年之内的行。如果能找到,
那么结果表中左输入对应行会超过三行。接下来按姓名和月份分组,找出COUNT大于3的就可以了。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | SELECT DISTINCT Name FROM ( SELECT Name , Year , COUNT (LYear) C FROM ( SELECT * FROM dbo.Prize P1 CROSS APPLY( SELECT TOP 3 Year LYear FROM dbo.Prize P2 WHERE P1. Name = P2. Name AND P2. Year >= P1. Year AND P2. Year - P1. Year <=2 ORDER BY Year ) AS D1 ) AS d2 GROUP BY Name , Year ) AS D3 WHERE D3.C >=3 |
2 第二种方式,使用CTE递归进行查询。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ; WITH cte1( name , year , count ) AS ( SELECT Name , MIN ( year ), 1 FROM dbo.Prize GROUP BY Name UNION ALL SELECT p. Name , p. Year , CASE WHEN p. Year = c. year + 1 THEN c. count +1 ElSE 1 END FROM dbo.Prize p JOIN cte1 c ON p. Name = c. name AND p. Year > c. year ) SELECT DISTINCT name FROM cte1 WHERE count >= 3 ORDER BY name |
这个递归的定位条件就是按名字分组,找出获奖年最小的那个。接下来就是递归实现的部分。用Prize表和cte表进行连接,连接的条件是名字相等,同时新加入行的获奖年份比
当前大。这种方式的关键是在CASE语句,如果找到的行的year比当前行的year大1,那么就更新count,为当前行的count+1.否则,说明当前行不是连续获奖的year,使count
计数归位,还原为1。最后只需要查找count大于等于3的行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库