找出唯一的区间
表格如下:
id num time
a 0 9:01
a 1 9:02
a 1 9:03
a 1 9:04
a 0 9:05
a 1 9:06
a 1 9:07
a 1 9:08
b 1 9:01
b 1 9:02
b 1 9:03
b 1 9:04
b 1 9:05
b 0 9:06
b 1 9:07
b 1 9:08
c 1 9:01
c 1 9:02
c 0 9:03
c 1 9:04
c 1 9:05
c 0 9:06
c 1 9:07
c 1 9:08
d 1 9:01
d 1 9:02
d 1 9:03
d 1 9:04
d 1 9:05
d 0 9:06
d 0 9:07
d 1 9:08
e 1 9:01
e 0 9:02
e 0 9:03
e 1 9:04
e 1 9:05
e 1 9:06
e 1 9:07
e 0 9:08
.. .. ...
希望找出 某段时间内 连续是1 的最长区间,而且一定保证是唯一的一个。
比如 e 9:04 9:07 全是1,而且 没有其他id 在9:04 9:07 重合。
b 9:01 9:05 与 d 9:01 9:05 也都是1 ,但是重合,所以排除.
希望 找出 e 9:04 9:07这个区间。
2000系统,
[最优解释]
DECLARE @timestamp NVARCHAR(4)
SET @timestamp='9:07'
--create #1
IF object_id('tempdb..#1')IS NOT NULL
DROP TABLE #1
SELECT
a.id,b.num,b.time,CONVERT(INT,0) AS count_id
INTO #1
FROM t1 AS a
INNER JOIN t1 AS b ON a.id=b.id AND b.time<=@timestamp AND b.time>ISNULL((SELECT MAX(time) FROM t1 AS x WHERE x.id=b.id AND x.time<=@timestamp AND x.num=0),'')
WHERE a.time<=@timestamp
AND EXISTS(SELECT 1 FROM t1 AS x WHERE x.id=a.id AND x.time=@timestamp AND x.num=1)
GROUP BY a.id,b.num,b.time
UPDATE a
SET count_id=(SELECT COUNT(id) FROM #1 WHERE id=a.id)
FROM #1 AS a
SELECT
a.id
,a.num
,a.time
FROM #1 AS a
WHERE NOT EXISTS(SELECT 1 FROM #1 AS x
WHERE a.id<>x.id AND count_id>a.count_id
)
AND NOT EXISTS(SELECT 1 FROM #1 AS x
WHERE a.id<>x.id AND x.count_id=a.count_id
)
---------------------------------
-- Author: HEROWANG(让你望见影子的墙)
-- Date : 2012-11-05 16:08:55
-- blog : blog.csdn.net/herowang
---------------------------------
IF OBJECT_ID('[tb]') IS NOT NULL
DROP TABLE [tb]
drop table #t
drop table #t2
go
CREATE TABLE [tb] (id VARCHAR(1),num INT,time datetime)
INSERT INTO [tb]
SELECT 'a',0,'9:01' UNION ALL
SELECT 'a',1,'9:02' UNION ALL
SELECT 'a',1,'9:03' UNION ALL
SELECT 'a',1,'9:04' UNION ALL
SELECT 'a',0,'9:05' UNION ALL
SELECT 'a',1,'9:06' UNION ALL
SELECT 'a',1,'9:07' UNION ALL
SELECT 'a',1,'9:08' UNION ALL
SELECT 'b',1,'9:01' UNION ALL
SELECT 'b',1,'9:02' UNION ALL
SELECT 'b',1,'9:03' UNION ALL
SELECT 'b',1,'9:04' UNION ALL
SELECT 'b',1,'9:05' UNION ALL
SELECT 'b',0,'9:06' UNION ALL
SELECT 'b',1,'9:07' UNION ALL
SELECT 'b',1,'9:08' UNION ALL
SELECT 'c',1,'9:01' UNION ALL
SELECT 'c',1,'9:02' UNION ALL
SELECT 'c',0,'9:03' UNION ALL
SELECT 'c',1,'9:04' UNION ALL
SELECT 'c',1,'9:05' UNION ALL
SELECT 'c',0,'9:06' UNION ALL
SELECT 'c',1,'9:07' UNION ALL
SELECT 'c',1,'9:08' UNION ALL
SELECT 'd',1,'9:01' UNION ALL
SELECT 'd',1,'9:02' UNION ALL
SELECT 'd',1,'9:03' UNION ALL
SELECT 'd',1,'9:04' UNION ALL
SELECT 'd',1,'9:05' UNION ALL
SELECT 'd',0,'9:06' UNION ALL
SELECT 'd',0,'9:07' UNION ALL
SELECT 'd',1,'9:08' UNION ALL
SELECT 'e',1,'9:01' UNION ALL
SELECT 'e',0,'9:02' UNION ALL
SELECT 'e',0,'9:03' UNION ALL
SELECT 'e',1,'9:04' UNION ALL
SELECT 'e',1,'9:05' UNION ALL
SELECT 'e',1,'9:06' UNION ALL
SELECT 'e',1,'9:07' UNION ALL
SELECT 'e',0,'9:08'
select px=identity(int,1,1),* into #t from tb
select distinct id,num,begintime=(select min(time) from #t where num=t.num and id=t.id and time<=t.time),
endtime=(select max(time) from #t where num=t.num and id=t.id and time>t.time and px<(select top 1 px from #t where num!=t.num and id=t.id and px>t.px))
into #t2
from [#t] t
where num=1
select top 1 *,diff=datediff(mi,begintime,endtime) from #t2
where endtime is not null
order by datediff(mi,begintime,endtime) desc
e11900-01-01 09:01:00.0001900-01-01 09:07:00.0006
----------------------------
-- Author :TravyLee
-- Date :2012-11-06 09:00:47
-- Version:
-- Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)
--Jul 9 2008 14:43:34
--Copyright (c) 1988-2008 Microsoft Corporation
--Developer Edition on Windows NT 6.1 <X86> (Build 7600: )
--
----------------------------
--> 测试数据:[test]
if object_id('[test]') is not null
drop table [test]
go
create table [test](
[id] varchar(1),
[num] int,
[time] time
)
insert [test]
select 'a',0,'9:01' union all
select 'a',1,'9:02' union all
select 'a',1,'9:03' union all
select 'a',1,'9:04' union all
select 'a',0,'9:05' union all
select 'a',1,'9:06' union all
select 'a',1,'9:07' union all
select 'a',1,'9:08' union all
select 'b',1,'9:01' union all
select 'b',1,'9:02' union all
select 'b',1,'9:03' union all
select 'b',1,'9:04' union all
select 'b',1,'9:05' union all
select 'b',0,'9:06' union all
select 'b',1,'9:07' union all
select 'b',1,'9:08' union all
select 'c',1,'9:01' union all
select 'c',1,'9:02' union all
select 'c',0,'9:03' union all
select 'c',1,'9:04' union all
select 'c',1,'9:05' union all
select 'c',0,'9:06' union all
select 'c',1,'9:07' union all
select 'c',1,'9:08' union all
select 'd',1,'9:01' union all
select 'd',1,'9:02' union all
select 'd',1,'9:03' union all
select 'd',1,'9:04' union all
select 'd',1,'9:05' union all
select 'd',0,'9:06' union all
select 'd',0,'9:07' union all
select 'd',1,'9:08' union all
select 'e',1,'9:01' union all
select 'e',0,'9:02' union all
select 'e',0,'9:03' union all
select 'e',1,'9:04' union all
select 'e',1,'9:05' union all
select 'e',1,'9:06' union all
select 'e',1,'9:07' union all
select 'e',0,'9:08'
--------------开始查询--------------------------
select
*
from
(select
*
from
(select
[id],
[num],
[time]
from
test
where
[time] between '9:01' and '9:05')t
where
not exists(select 1 from (select
[id],
[num],
[time]
from
test
where
[time] between '9:01' and '9:05')a where a.id=t.id and a.num<>t.num))a
where
not exists(select 1 from (select
*
from
(select
[id],
[num],
[time]
from
test
where
[time] between '9:01' and '9:05')t
where
not exists(select 1 from (select
[id],
[num],
[time]
from
test
where
[time] between '9:01' and '9:05')a where a.id=t.id and a.num<>t.num))m where a.time=m.time and a.id<>m.id)
/*
id num time
---- ----------- ----------------
(0 行受影响)
*/
select
*
from
(select
*
from
(select
[id],
[num],
[time]
from
test
where
[time] between '9:04' and '9:07')t
where
not exists(select 1 from (select
[id],
[num],
[time]
from
test
where
[time] between '9:04' and '9:07')a where a.id=t.id and a.num<>t.num))a
where
not exists(select 1 from (select
*
from
(select
[id],
[num],
[time]
from
test
where
[time] between '9:04' and '9:07')t
where
not exists(select 1 from (select
[id],
[num],
[time]
from
test
where
[time] between '9:04' and '9:07')a where a.id=t.id and a.num<>t.num))m where a.time=m.time and a.id<>m.id)
/*
id num time
---- ----------- ----------------
e 1 09:04:00.0000000
e 1 09:05:00.0000000
e 1 09:06:00.0000000
e 1 09:07:00.0000000
(4 行受影响)
*/
USE test
go
--if object_id('t1') is not null
--drop table t1
--Go
--Create table t1([id] nvarchar(1),[num] nvarchar(1),[time] datetime)
--Insert into t1
--Select N'a',N'0','9:01'
--Union all Select N'a',N'1','9:02'
--Union all Select N'a',N'1','9:03'
--Union all Select N'a',N'1','9:04'
--Union all Select N'a',N'0','9:05'
--Union all Select N'a',N'1','9:06'
--Union all Select N'a',N'1','9:07'
--Union all Select N'a',N'1','9:08'
--Union all Select N'b',N'1','9:01'
--Union all Select N'b',N'1','9:02'
--Union all Select N'b',N'1','9:03'
--Union all Select N'b',N'1','9:04'
--Union all Select N'b',N'1','9:05'
--Union all Select N'b',N'0','9:06'
--Union all Select N'b',N'1','9:07'
--Union all Select N'b',N'1','9:08'
--Union all Select N'c',N'1','9:01'
--Union all Select N'c',N'1','9:02'
--Union all Select N'c',N'0','9:03'
--Union all Select N'c',N'1','9:04'
--Union all Select N'c',N'1','9:05'
--Union all Select N'c',N'0','9:06'
--Union all Select N'c',N'1','9:07'
--Union all Select N'c',N'1','9:08'
--Union all Select N'd',N'1','9:01'
--Union all Select N'd',N'1','9:02'
--Union all Select N'd',N'1','9:03'
--Union all Select N'd',N'1','9:04'
--Union all Select N'd',N'1','9:05'
--Union all Select N'd',N'0','9:06'
--Union all Select N'd',N'0','9:07'
--Union all Select N'd',N'1','9:08'
--Union all Select N'e',N'1','9:01'
--Union all Select N'e',N'0','9:02'
--Union all Select N'e',N'0','9:03'
--Union all Select N'e',N'1','9:04'
--Union all Select N'e',N'1','9:05'
--Union all Select N'e',N'1','9:06'
--Union all Select N'e',N'1','9:07'
--Union all Select N'e',N'0','9:08'
--create #1
IF object_id('tempdb..#1')IS NOT NULL
DROP TABLE #1
SELECT
ROW_NUMBER()OVER(PARTITION BY id ORDER BY time) AS Row
,*
INTO #1
FROM t1
--create #2
IF object_id('tempdb..#2')IS NOT NULL
DROP TABLE #2
SELECT
ROW_NUMBER()OVER(ORDER BY id ASC)AS Row
,id
,CONVERT(NVARCHAR(4000),'')AS Section_tmp
,CONVERT(BIT,0)AS Flag
INTO #2
FROM #1 GROUP BY id
DECLARE @Sql NVARCHAR(MAX)
-- update #2
WHILE EXISTS(SELECT 1 FROM #2 WHERE Flag=0)
BEGIN
SET @Sql=''
SELECT @Sql=@Sql+CASE WHEN num=1 THEN LTRIM(Row) ELSE ',' END
FROM #1
WHERE id=(SELECT TOP 1 id FROM #2 WHERE Flag=0 ORDER BY Row)
UPDATE #2
SET Section_tmp=@Sql
,Flag=1
WHERE id=(SELECT TOP 1 id FROM #2 WHERE Flag=0 ORDER BY Row)
END
--create #3
IF object_id('tempdb..#3')IS NOT NULL
DROP TABLE #3
CREATE TABLE #3(id NVARCHAR(1),Section bigint)
WHILE EXISTS(SELECT 1 FROM #2 WHERE Flag=1)
BEGIN
SET @Sql=''
SELECT @Sql=LTRIM(id)+''','''+REPLACE(Section_tmp,',',''' UNION SELECT '''+LTRIM(id)+''',''')+''''
FROM #2
WHERE id=(SELECT TOP 1 id from #2 WHERE Flag=1 ORDER BY Row)
UPDATE #2 SET Flag=0 WHERE id=(SELECT TOP 1 id FROM #2 WHERE Flag=1 ORDER BY Row)
INSERT INTO #3
EXEC ('SELECT N'''+@Sql)
END
-- Result 1: 相同id,相同區間長度 查詢全部的區間.
SELECT a.id,a.num,a.time FROM #1 AS a,#3 AS b
WHERE a.id=b.id
AND CHARINDEX(LTRIM(a.Row),b.Section)>0
AND NOT EXISTS(SELECT 1 FROM #3 AS x
WHERE x.id=b.id AND LEN(x.Section)>LEN(b.Section)
)
GROUP BY a.id,a.num,a.time
ORDER BY a.id,a.time ASC
Go
USE test
go
--if object_id('t1') is not null
-- drop table t1
--Go
--Create table t1([id] nvarchar(1),[num] nvarchar(1),[time] datetime)
--Insert into t1
--Select N'a',N'0','9:01'
--Union all Select N'a',N'1','9:02'
--Union all Select N'a',N'1','9:03'
--Union all Select N'a',N'1','9:04'
--Union all Select N'a',N'0','9:05'
--Union all Select N'a',N'1','9:06'
--Union all Select N'a',N'1','9:07'
--Union all Select N'a',N'1','9:08'
--Union all Select N'b',N'1','9:01'
--Union all Select N'b',N'1','9:02'
--Union all Select N'b',N'1','9:03'
--Union all Select N'b',N'1','9:04'
--Union all Select N'b',N'1','9:05'
--Union all Select N'b',N'0','9:06'
--Union all Select N'b',N'1','9:07'
--Union all Select N'b',N'1','9:08'
--Union all Select N'c',N'1','9:01'
--Union all Select N'c',N'1','9:02'
--Union all Select N'c',N'0','9:03'
--Union all Select N'c',N'1','9:04'
--Union all Select N'c',N'1','9:05'
--Union all Select N'c',N'0','9:06'
--Union all Select N'c',N'1','9:07'
--Union all Select N'c',N'1','9:08'
--Union all Select N'd',N'1','9:01'
--Union all Select N'd',N'1','9:02'
--Union all Select N'd',N'1','9:03'
--Union all Select N'd',N'1','9:04'
--Union all Select N'd',N'1','9:05'
--Union all Select N'd',N'0','9:06'
--Union all Select N'd',N'0','9:07'
--Union all Select N'd',N'1','9:08'
--Union all Select N'e',N'1','9:01'
--Union all Select N'e',N'0','9:02'
--Union all Select N'e',N'0','9:03'
--Union all Select N'e',N'1','9:04'
--Union all Select N'e',N'1','9:05'
--Union all Select N'e',N'1','9:06'
--Union all Select N'e',N'1','9:07'
--Union all Select N'e',N'0','9:08'
DECLARE @timestamp NVARCHAR(4)
SET @timestamp='9:07'
--create #1
IF object_id('tempdb..#1')IS NOT NULL
DROP TABLE #1
SELECT
a.id,b.num,b.time,CONVERT(INT,0) AS count_id
INTO #1
FROM t1 AS a
INNER JOIN t1 AS b ON a.id=b.id AND b.time<=@timestamp AND b.time>ISNULL((SELECT MAX(time) FROM t1 AS x WHERE x.id=b.id AND x.time<=@timestamp AND x.num=0),'')
WHERE a.time<=@timestamp
AND EXISTS(SELECT 1 FROM t1 AS x WHERE x.id=a.id AND x.time=@timestamp AND x.num=1)
GROUP BY a.id,b.num,b.time
UPDATE a
SET count_id=(SELECT COUNT(id) FROM #1 WHERE id=a.id)
FROM #1 AS a
SELECT * FROM #1 AS a
WHERE NOT EXISTS(SELECT 1 FROM #1 AS x
WHERE a.id<>x.id AND count_id>a.count_id
)
AND NOT EXISTS(SELECT 1 FROM #1 AS x
WHERE a.id<>x.id AND x.count_id=a.count_id
)
DECLARE @tmp NVARCHAR(50),@Result NVARCHAR(50)