读书人

高难度SQL语句有关问题~100分答谢

发布时间: 2012-01-11 22:28:46 作者: rapoo

高难度SQL语句问题~~100分答谢
有这个一个迷糊的问题我想处理。先把情况说明一下
有表A:里面保存了一些人的请假信息
personcode starttime endtime
000001 2007-05-10 13:15:00.000 2007-05-10 16:15:00.000
000002 2007-05-16 08:15:00.000 2007-05-18 13:15:00.000


上面保存的信息就是说,人000001 请了一次假 开始时间和结束时间都有
人000002也请了一次假,一个人当然可以在不同时间请多次假

现在我要统计出,在一个时间范围之内(精确到秒),所有人请假的总时长(秒)
不过这里面要考虑两个问题
1.早上8点上班到下午5点30上班,如果是跨天的记录在这个时间范围内不应该被统计进来。
2.在需要统计的时间范围之内,如果有时间被截断,那么就按统计范围给这个时间截段统计

例如:上述表中人000002的,如果我的统计范围设置成20070516-20070517
那么统计的结果应该是这个人从2007年5月16日早8点15到2007年05月17日晚5点30分的秒数统计,然后再还要排掉晚上5点30到第2天早上8点这段下班时间。

里面涉及到,请假开始时间结束时间,上班时间下班时间,统计范围的开始时间结束时间。我写了一上午,现在头有点晕,谁写个语句参考一下

这个问题还是简化的,因为某日的上班时间和下班时间还需要另一个表计算出来,所以更晕了


[解决办法]
create table #qj(personcode varchar(10),starttime datetime,endtime datetime)
insert #qj select
'000001 ', '2007-05-10 13:15:00.000 ', '2007-05-10 16:15:00.000 ' insert #qj select
'000002 ', '2007-05-16 08:15:00.000 ', '2007-05-18 13:15:00.000 ' insert #qj select
'000001 ', '2007-05-11 13:15:00.000 ', '2007-05-12 16:15:00.000 ' insert #qj select
'000002 ', '2007-05-19 08:15:00.000 ', '2007-05-20 13:15:00.000 '

select personcode,sum(
datediff(ss,
(case when '2007-05-16 '> starttime then '2007-05-16 ' else starttime end),
(case when dateadd(dd,1, '2007-05-19 ') <endtime then dateadd(dd,1, '2007-05-19 ') else endtime end))
-9000*datediff(dd,
(case when '2007-05-16 '> starttime then '2007-05-16 ' else starttime end),
(case when dateadd(dd,1, '2007-05-19 ') <endtime then dateadd(dd,1, '2007-05-19 ') else endtime end))
)秒差
from #qj
where not(starttime> =dateadd(dd,1, '2007-05-19 ') or endtime <= '2007-05-16 ')
group by personcode

personcode 秒差
---------- -----------
000002 220500

(所影响的行数为 1 行)
select datediff(ss, '2007-05-05 05:30:00 ', '2007-05-05 08:00:00 ')--9000
[解决办法]
select datediff(ss, '2007-05-05 05:30:00 ', '2007-05-05 08:00:00 ')--9000
班时间到第2天上班时间这段时间 是9000秒
-9000*datediff(dd,
(case when '2007-05-16 '> starttime then '2007-05-16 ' else starttime end),
(case when dateadd(dd,1, '2007-05-19 ') <endtime then dateadd(dd,1, '2007-05-19 ') else endtime end))
查询时间的开始与记录的开始比较,取最大值,
查询时间的结束与记录的结束比较,取最小值,
它们之间差的天数*每天差的9000秒不是你要的?
[解决办法]
--建立环境,感谢wgzaaa

create table #qj(personcode varchar(10),starttime datetime,endtime datetime)
insert #qj select
'000001 ', '2007-05-10 13:15:00.000 ', '2007-05-10 16:15:00.000 ' insert #qj select
' 000002 ', '2007-05-16 08:15:00.000 ', '2007-05-18 13:15:00.000 ' insert #qj select
'000001 ', '2007-05-11 13:15:00.000 ', '2007-05-12 16:15:00.000 ' insert #qj select
'000002 ', '2007-05-19 08:15:00.000 ', '2007-05-20 13:15:00.000 '


---参数


declare @BeginDate datetime
declare @EndDate datetime

--查询条件
set @BeginDate= '2007-5-16 8:00 '
set @endDate= '2007-5-19 17:30 '

--思路是先按天拆分请假记录
declare @BeginDate1 datetime
declare @EndDate1 datetime
set @BeginDate1=@BeginDate
set @EndDate1=convert(varchar(10),@BeginDate,120)+ ' 17:30 '

declare @t table(personcode varchar(10),starttime datetime,endtime datetime)

--循环,每天处理一次
while @EndDate1 <=@EndDate
begin

insert @t
select personcode,
case when starttime <@BeginDate1 then @BeginDate1 else starttime end as starttime,
case when endtime> @endDate1 then @endDate1 else endtime end as endtime
from #qj
where starttime between @BeginDate1 and @endDate1
or endtime between @BeginDate1 and @endDate1
set @beginDate1=dateadd(day,1,@beginDate1)
set @EndDate1=dateadd(day,1,@endDate1)
end

--再汇总计算秒数
select personcode,sum(datediff(ss,starttime,endtime)) as times
from @t
group by personcode

--结果(没验证,不知道对不对)
personcode times
---------- -----------
000002 85500

(所影响的行数为 1 行)

--删除环境
drop table #qj

[解决办法]
发现个小问题(其实问题很大,不能不修改)

--建立环境,感谢wgzaaa

create table #qj(personcode varchar(10),starttime datetime,endtime datetime)
insert #qj select
'000001 ', '2007-05-10 13:15:00.000 ', '2007-05-10 16:15:00.000 ' insert #qj select
' 000002 ', '2007-05-16 08:15:00.000 ', '2007-05-18 13:15:00.000 ' insert #qj select
'000001 ', '2007-05-11 13:15:00.000 ', '2007-05-12 16:15:00.000 ' insert #qj select
'000002 ', '2007-05-19 08:15:00.000 ', '2007-05-20 13:15:00.000 '


---参数
declare @BeginDate datetime
declare @EndDate datetime

--查询条件
set @BeginDate= '2007-5-16 8:00 '
set @endDate= '2007-5-19 17:30 '

--思路是先按天拆分请假记录
declare @BeginDate1 datetime
declare @EndDate1 datetime
set @BeginDate1=@BeginDate
set @EndDate1=convert(varchar(10),@BeginDate,120)+ ' 17:30 '

declare @t table(personcode varchar(10),starttime datetime,endtime datetime)

--循环,每天处理一次
while @EndDate1 <=@EndDate
begin

insert @t
select personcode,
case when starttime <@BeginDate1 then @BeginDate1 else starttime end as starttime,
case when endtime> @endDate1 then @endDate1 else endtime end as endtime
from #qj
where @BeginDate1 between starttime and endtime
or @enddate1 between starttime and endtime
set @beginDate1=dateadd(day,1,@beginDate1)
set @EndDate1=dateadd(day,1,@endDate1)
end

--再汇总计算秒数
select personcode,sum(datediff(ss,starttime,endtime)) as times
from @t
group by personcode

--结果(没验证,不知道对不对)
personcode times
---------- -----------
000002 119700

(所影响的行数为 1 行)


--删除环境
drop table #qj

[解决办法]
如果参数是
2007-5-11 8:00
2007-5-19 17:30

结果是:
personcode times
---------- -----------
000001 45000
000002 119700

(所影响的行数为 2 行)

[解决办法]
也感谢Yang_(扬帆破浪 知道细节没有处理好,本来以为楼主只要思路,自以为思路还不错
兴奋得蒙住了眼睛
select personcode,sum(


datediff(ss,
(case when '2007-05-16 08:00:00 '> starttime then '2007-05-16 08:00:00 ' else starttime end),
(case when '2007-05-19 17:30:00 ' <endtime then '2007-05-19 17:30:00 ' else endtime end))
-52200*datediff(dd,
(case when '2007-05-16 08:00:00 '> starttime then '2007-05-16 08:00:00 ' else starttime end),
(case when '2007-05-19 17:30:00 ' <endtime then '2007-05-19 17:30:00 ' else endtime end))
)秒差
from #qj
where not(starttime> =dateadd(dd,1, '2007-05-19 ') or endtime <= '2007-05-16 ')
group by personcode
------------
personcode 秒差
---------- -----------
000002 119700

(所影响的行数为 1 行)
select datediff(ss, '2007-05-05 17:30:00 ', '2007-05-06 08:00:00 ')--52200
下面改成参数
declare @a datetime,@b datetime
select @a= '2007-05-11 08:00:00 ',@b= '2007-05-19 17:30:00 '
--select @a= '2007-05-16 08:00:00 ',@b= '2007-05-19 17:30:00 '
select personcode,sum(
datediff(ss,
(case when @a> starttime then @a else starttime end),
(case when @b <endtime then @b else endtime end))
-52200*datediff(dd,
(case when @a> starttime then @a else starttime end),
(case when @b <endtime then @b else endtime end))
)秒差
from #qj
where not(starttime> =dateadd(dd,1,@b) or endtime <=@a)
group by personcode
---------------
personcode 秒差
---------- -----------
000001 45000
000002 119700

(所影响的行数为 2 行)

读书人网 >SQL Server

热点推荐