借帖子中的问题 http://topic.csdn.net/u/20080916/08/fde28e86-7c54-4d8b-8e27-542f4bbff720.html,回忆SQL Server 大师级人物 Ken Henderson
问题如下:
数据结构
a b c
1 x1 11
2 x2 15
3 x3 15
4 x3 14
5 x2 15
6 x4 13
第一条sql,统计列b中有几种情况(题中有x1,x2,x3,x4共四种)
第二条,查询C最大值的最大连续记录集(查询出2和3行),好像有点难,这条给50分。
参考大师Ken Henderson 的思路,编写的代码,虽然看上去不容易懂,但确实精彩,精妙绝伦:
set nocount on declare @temp table (k1 int identity, b varchar(10), c1 int) insert into @temp values('x1',11) insert into @temp values('x2',13) insert into @temp values('x3',15) insert into @temp values('x3',15) insert into @temp values('x2',12) insert into @temp values('x9',10) insert into @temp values('x1',11) insert into @temp values('x6',15) insert into @temp values('x3',15) insert into @temp values('x5',12) declare @max int = (select max(c1) from @temp) declare @temp_max table(starts int,ends int,diff int ) insert into @temp_max select starts=v.k1, ends=isnull( min(case when v.k1<a.k1 and a.c1<>@max then a.k1 else null end )-1, max(case when v.k1<a.k1 then a.k1 else v.k1 end) ), isnull( min(case when v.k1<a.k1 and a.c1<>@max then a.k1 else null end)-1, max(case when v.k1<a.k1 then a.k1 else v.k1 end) )-v.k1 as diff from @temp v inner join @temp a on v.c1=@max group by v.k1 having isnull( min(case when v.k1<a.k1 and a.c1<>@max then a.k1 else null end)-1, max(case when v.k1<a.k1 then a.k1 else v.k1 end) ) >=v.k1 and isnull( max(case when v.k1>a.k1 and a.c1<>@max then a.k1 else null end) + 1, min(case when v.k1>a.k1 then a.k1 else v.k1 end) ) = v.k1 select * from @temp t where exists ( select * from @temp_max where diff=(select max(diff) from @temp_max) and (t.k1 between starts and ends) )
运行结果如下:
k1 b c1
-----------
3 x3 15
4 x3 15
8 x6 15
9 x3 15
这是一开始我自己写得代码,挺长的,是用了双层的游标:
create table tablename(a int ,b varchar(10),c int) insert into tablename values(1, 'x1 ',11) insert into tablename values(2, 'x2 ',15) insert into tablename values(3, 'x3 ',15 ) insert into tablename values(4, 'x3 ',14 ) insert into tablename values(5, 'x2 ',15 ) insert into tablename values(6, 'x4 ',13 ) insert into tablename values(7, 'x4 ',15 ) insert into tablename values(8, 'x6 ',15 ) insert into tablename values(9, 'x4 ',15 ) declare @temp_max table(a int ,b varchar(10),c int) declare @temp table(a int ,b varchar(10),c int) declare @maxcount int set @maxcount=0 declare @max_c int select @max_c=max(c) from tablename declare @recordcount int set @recordcount=0 declare @a int declare @b varchar(10) declare @c int declare max_cousor cursor for select * from tablename open max_cousor fetch max_cousor into @a,@b,@c while @@fetch_status =0 begin if(@c=@max_c) begin insert into @temp values(@a,@b,@c) set @recordcount=@recordcount+1 fetch max_cousor into @a,@b,@c while @@fetch_status=0 begin if(@c=@max_c) begin insert into @temp values(@a,@b,@c) fetch max_cousor into @a,@b,@c set @recordcount=@recordcount+1 end else begin break end end end if(@maxcount=@recordcount and @maxcount <> 0) begin if(@maxcount> =1) insert into @temp_max values(null,null,null) insert into @temp_max select * from @temp set @recordcount=0 delete from @temp end else begin if(@maxcount <@recordcount) begin delete from @temp_max insert into @temp_max select * from @temp delete from @temp set @maxcount=@recordcount set @recordcount=0 end else set @recordcount=0 delete from @temp end fetch max_cousor into @a,@b,@c end close max_cousor deallocate max_cousor select a,b,c,@maxcount as '连续的个数 ' from @temp_max
最近又想到一种办法:
set nocount on declare @temp table (k1 int identity, b varchar(10), c1 int) insert into @temp values('x1',11) insert into @temp values('x2',13) insert into @temp values('x3',15) insert into @temp values('x3',15) insert into @temp values('x3',15) insert into @temp values('x2',12) insert into @temp values('x9',10) insert into @temp values('x1',11) insert into @temp values('x6',15) insert into @temp values('x3',15) insert into @temp values('x3',15) insert into @temp values('x5',12) declare @max int = (select max(c1) from @temp) ;with tt as ( select t.k1, t.c1, t.b, ROW_NUMBER() over(partition by c1 order by k1) rnum from @temp t where t.c1 = @max ), ttt as ( select t1.k1, T1.rnum AS R1, T2.k1 AS K2, T2.rnum AS R2, t2.k1-t1.k1 as diff From tt t1 inner join tt t2 on T1.K1 < T2.K1 and t1.rnum <> t2.rnum WHERE t2.k1 - t1.k1 = t2.rnum - t1.rnum --两者之间的差值相等 ), diff as ( select max(diff) as maxDiff from ttt ) select t.* from @temp t inner join ttt on t.k1 between ttt.k1 and ttt.K2 inner join diff d on d.maxDiff = ttt.diff