在论坛中出现的比较难的sql问题:7(子查询 判断某个字段的值是否连续)

时间:2021-05-08 01:04:38
最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。

所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。


1、求一个聚合的SQL该怎么写

http://bbs.csdn.net/topics/390640648?page=1#post-396068172

有这样的数据
员工    开始日期                     终了日期
A       2013-05-01 00:00:00.000      2013-06-08 00:00:00.000
A       2013-09-02 00:00:00.000      2013-12-31 00:00:00.000
A       2013-09-05 00:00:00.000      NULL


求员工A的所能表示的最大范围的日期,取日期的并集,最后结果应该如下:
员工    开始日期                     终了日期
A       2013-05-01 00:00:00.000      2013-06-08 00:00:00.000
A       2013-09-02 00:00:00.000      NULL

请问谁知道这样的SQL语句该如何写。


我的解法:

;with t(员工 , 开始日期,终了日期)
as
(
select 'A', '2013-05-01 00:00:00.000','2013-06-08 00:00:00.000'
union all select 'A','2013-09-02 00:00:00.000','2013-12-31 00:00:00.000'
union all select 'A','2013-09-05 00:00:00.000',NULL
union all select 'A','2013-09-15 00:00:00.000',	'2013-11-08 00:00:00.000'
),

tt
as
(
select 员工,开始日期,终了日期,
       (select MIN(t2.开始日期)
        from t t2
        where t1.员工 = t2.员工
              and t1.开始日期 between t2.开始日期 and isnull(t2.终了日期,'3000-01-01')
       ) as min_开始日期,
       
       (select max(isnull(t2.终了日期,'3000-01-01'))
        from t t2
        where t1.员工 = t2.员工
              and t1.开始日期 between t2.开始日期 and isnull(t2.终了日期,'3000-01-01')
       ) as max_终了日期    
from t t1
)

select 员工,min_开始日期 as 开始日期,
       nullif(max(max_终了日期),'3000-01-01') as  终了日期
from tt
group by 员工,min_开始日期
/*
员工	 开始日期	                 终了日期
A	 2013-05-01 00:00:00.000	2013-06-08 00:00:00.000
A	 2013-09-02 00:00:00.000	NULL
*/


2、sql中怎么判断某个字段的值是否连续?

http://bbs.csdn.net/topics/390615670

比如:A表的字段AID的值为:1、2、4、5、7、8、10
怎么用sql查询出2、5、8的结果呢?
要查的结果就是查询这组数据从哪里开始不连续的。

我的解法:

create table A(AID int)
 
insert into A(AID)
 select 1 union all
 select 2 union all
 select 4 union all
 select 5 union all
 select 7 union all
 select 8 union all
 select 10

select aid
from
(
select a.aid,
       (select min(aid) from a aa where aa.aid > a.aid) min_aid
from A 
)a
where aid +1 < min_aid
/*
aid
2
5
8
*/