--sql2012
CREATE TABLE times(
[a] [datetime],
[b] [datetime]
)
--下面的数据去重复求和是3小时。我怎么能查出3来?
insert into times(a,b) values('2010-01-01 9:00:00','2010-01-01 10:00:00')
insert into times(a,b) values('2010-01-01 8:00:00','2010-01-01 9:30:00')
insert into times(a,b) values('2010-01-01 11:00:00','2010-01-01 12:00:00')
--method one
with a as(
select min(a) as a,max(b) as b from times
)
select a,b,datediff(hour,a,b) as '和' from a
--结果展示(去重复后求和是4小时)
/*
a b 和
----------------------- ----------------------- -----------
2010-01-01 08:00:00.000 2010-01-01 12:00:00.000 4(1 行受影响) */
--method two select sum(datediff(hour,a,b))as '和'
from times
--结果展示
/*
和
-----------
3(1 行受影响)
*//*
楼主没有说明,什么去重复求和,所以无法给出肯定的答案,仅供参考
*/
CREATE TABLE times(
[a] [datetime],
[b] [datetime]
)
--下面的数据去重复求和是3小时。我怎么能查出3来?
insert into times(a,b) values('2010-01-01 9:00:00','2010-01-01 10:00:00')
insert into times(a,b) values('2010-01-01 8:00:00','2010-01-01 9:30:00')
insert into times(a,b) values('2010-01-01 11:00:00','2010-01-01 12:00:00')
--method one
with a as(
select min(a) as a,max(b) as b from times
)
select a,b,datediff(hour,a,b) as '和' from a
--结果展示(去重复后求和是4小时)
/*
a b 和
----------------------- ----------------------- -----------
2010-01-01 08:00:00.000 2010-01-01 12:00:00.000 4(1 行受影响) */
--method two select sum(datediff(hour,a,b))as '和'
from times
--结果展示
/*
和
-----------
3(1 行受影响)
*//*
楼主没有说明,什么去重复求和,所以无法给出肯定的答案,仅供参考
*/
--结果是12600
CREATE TABLE times(
[a] [datetime],
[b] [datetime]
)
--下面的数据去重复求和是3小时。我怎么能查出3来?
insert into times(a,b) values('2010-01-01 9:00:00','2010-01-01 10:00:00')
insert into times(a,b) values('2010-01-01 8:00:00','2010-01-01 9:30:00')
insert into times(a,b) values('2010-01-01 11:00:00','2010-01-01 12:00:00')
select * from times order by a--结果展示
/*
a b
----------------------- -----------------------
2010-01-01 08:00:00.000 2010-01-01 09:30:00.000
2010-01-01 09:00:00.000 2010-01-01 10:00:00.000
2010-01-01 11:00:00.000 2010-01-01 12:00:00.000(3 行受影响)*/
--我看过的书都说,top100+orderby,是没用的,今天你打破了这个说法
with a as (
select top (100)percent a,b,lead(a) over(order by a) as lead_a,lag(a) over(order by a) as lag_a,lag(b) over(order by a) as lag_b,lead(b) over(order by a) as lead_b
from times
order by a,b
)
--这里逻辑众多,需要你独自完善,我写的这个是省略的
select sum(case when lead_a is not null and b >lead_a then datediff(second,a,lead_a)
when lead_a is not null and b<lead_a and b not between lag_a and lag_b then datediff(second,a,b)
when lead_a is null and a>lag_a then datediff(second,a,b)
end)
from a
/*
-----------
10800(1 行受影响)
*/
CREATE TABLE times(
[a] [datetime],
[b] [datetime]
)
--下面的数据去重复求和是3小时。我怎么能查出3来?
insert into times(a,b) values('2010-01-01 9:00:00','2010-01-01 10:00:00')
insert into times(a,b) values('2010-01-01 8:00:00','2010-01-01 9:30:00')
insert into times(a,b) values('2010-01-01 11:00:00','2010-01-01 12:00:00')
insert into times(a,b) values('2010-01-01 11:00:00','2010-01-01 12:00:00')
insert into times(a,b) values('2010-01-01 08:00:00','2010-01-01 11:00:00')
insert into times(a,b) values('2010-01-01 07:00:00','2010-01-01 11:00:00')
insert into times(a,b) values('2010-01-01 07:00:00','2010-01-01 9:00:00')
insert into times(a,b) values('2010-01-01 10:00:00','2010-01-01 12:00:00')
insert into times(a,b) values('2010-01-01 09:00:00','2010-01-01 12:00:00') select * from times order by a
--结果展示
/*
a b
----------------------- -----------------------
2010-01-01 07:00:00.000 2010-01-01 11:00:00.000
2010-01-01 07:00:00.000 2010-01-01 09:00:00.000
2010-01-01 08:00:00.000 2010-01-01 11:00:00.000
2010-01-01 08:00:00.000 2010-01-01 09:30:00.000
2010-01-01 09:00:00.000 2010-01-01 10:00:00.000
2010-01-01 09:00:00.000 2010-01-01 12:00:00.000
2010-01-01 10:00:00.000 2010-01-01 12:00:00.000
2010-01-01 11:00:00.000 2010-01-01 12:00:00.000
2010-01-01 11:00:00.000 2010-01-01 12:00:00.000
2010-01-01 11:00:00.000 2010-01-01 11:00:00.000
2010-01-01 16:00:00.000 2010-01-01 20:00:00.000(11 行受影响)*/
WITH A AS --过滤掉相同的列
(
SELECT DISTINCT A,B FROM TIMES
),
B AS --排序,同时筛选出来跨度过长的列,并排除a=b,a>b的列
(SELECT A,B ,ROW_NUMBER() OVER(ORDER BY A,B) AS RN,DATEDIFF(SECOND,A,B) AS diff FROM A where b>a
),
C as -- 筛选出跨度最大的行
(
select top 1 a,b,diff,rn from B
order by diff desc,a asc,b asc
),
D as (
select b.a as ba,b.b as bb,b.diff as b_diff,c.a as max_a,c.b as max_b,c.diff as max_diff from b
left outer join C on ((c.rn<=b.rn and b.b>=c.b ) or (c.rn>b.rn and b.a <c.a)) and b.a>=c.a --and c.diff<=b.diff--过滤掉部分完全重复的行
where c.a is not null and c.b is not null
),
F as(
select ba as a ,bb as b,b_diff,row_number() over(order by ba,bb) as rn
from D where (max_a>=ba and max_b<=bb) or (ba>max_a and bb>max_b) --完全过滤掉重复行
)
select sum(case when f1.a is not null and f2.a is null and f.b>f1.a then f.b_diff
when f1.a is not null and f2.a is null and f.b<=f1.a then f.b_diff
when f1.a is not null and f2.a is not null and f.a <f2.b and f.a>f2.a then datediff(second,f2.b,f.b)
when f1.a is not null and f2.a is not null and f.a>f2.a and f.b<=f2.b then 0
when f1.a is not null and f2.a is not null and f.a>f2.b then f.b_diff
when f1.a is null and f2.a is not null and f.a>f2.b then f.b_diff
else 0 end )
from f left outer join f as f1 on f1.rn-1 =f.rn
left outer join f as f2 on f2.rn+1 =f.rn where f2.a<f.a--结果展示(注:该语句仅为sql2005以及以上版本可用,但是如果你是sql2012可以更精简,这个)
/*
-----------
18000(1 行受影响) */
---新方法
select * from times
/*
a b
----------------------- -----------------------
2010-01-01 09:00:00.000 2010-01-01 10:00:00.000
2010-01-01 08:00:00.000 2010-01-01 09:30:00.000
2010-01-01 11:00:00.000 2010-01-01 12:00:00.000
2010-01-01 11:00:00.000 2010-01-01 12:00:00.000
2010-01-01 11:00:00.000 2010-01-01 11:00:00.000
2010-01-01 08:00:00.000 2010-01-01 11:00:00.000
2010-01-01 07:00:00.000 2010-01-01 11:00:00.000
2010-01-01 07:00:00.000 2010-01-01 09:00:00.000
2010-01-01 16:00:00.000 2010-01-01 20:00:00.000
2010-01-01 10:00:00.000 2010-01-01 12:00:00.000
2010-01-01 09:00:00.000 2010-01-01 12:00:00.000(11 行受影响)
*/
;WITH A AS --过滤掉相同的列
(
SELECT DISTINCT A,B FROM TIMES
),
B AS --排序,同时筛选出来跨度过长的列,并排除a=b,a>b的列
(
SELECT A,B ,DATEDIFF(SECOND,A,B) AS diff FROM A where b>a
),
C as
(select a,b,row_number() over(partition by a order by b) as rn, cnt=(select count(*) from b as b1 where b1.a=b.a group by a) from b ),
d as
(
select a,b ,row_number() over(partition by b order by a) as rn from c where rn=cnt
),e as
(
select a,b,row_number()over( order by a) as rn,datediff(second,a,b) as diff from d where rn =1
)
--此方法比较靠谱select sum(case when e1.a is not null and e2.a is null then e.diff
when e1.a is not null and e2.a is not null and e.b >e2.a then datediff(second,e2.b,e.b)
when e1.a is not null and e2.a is not null and e.b<=e2.a then e.diff
when e1.a is null and e2.a is not null and e.a<e2.b then datediff(second,e2.b,e.b)
when e1.a is null and e2.a is not null and e.a>=e2.b then e.diff
else 0 end )
from e left outer join e as e1 on e1.rn-1 =e.rn
left outer join e as e2 on e2.rn+1 =e.rn /*
-----------
32400(1 行受影响)
*/