导航
  • 主页
  • 基础类
  • 应用实例
  • 新技术前沿

这类问题怎么解决最好?

funsuzhou 2006-01-23 03:00:58
我要计算2006年任何两天之间扣除休息天的天数。
因为休息的天数不都是星期六、日,有的时候停电,还有春节放假、五一放假等,所以只考虑星期六、日是休息天是不合适的,这类问题怎么解决比较好呢?
...全文
152 点赞 收藏 12
写回复
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
funsuzhou 2006-01-24
请各位高手帮忙看看,有没有更好的方法,如果没有,那我把我的这个方法贴出来给需要用的朋友们参考一下!

--测试:
create table HCSZ_REST_DATE(ymd int)
insert into tb_Test
select 20060101 union all
select 20060107 union all
select 20060108 union all
select 20060114 union all
select 20060115 union all
select 20060121 union all
select 20060122 union all
select 20060128 union all
select 20060129 union all
select 20060130 union all
select 20060131 union all
select 20060201 union all
select 20060202 union all
select 20060203 union all
select 20060204 union all
select 20060205 union all
select 20060211 union all
select 20060212 union all
select 20060218 union all
select 20060219 union all
select 20060226 union all
select 20060304


--创建自定义函数
CREATE function dbo.GetEndDateSubtractStartDate (@startDate varchar(8),@endDate varchar(8))
returns int
as
begin
declare @intFlag int
set @intFlag=1
if(@startDate>@endDate)
begin
declare @temp varchar(8)
set @temp=@startDate
set @startDate=@endDate
set @endDate=@temp
set @intFlag=-1
end
declare @re int
if @startDate=@endDate or (
(select count(*)from HCSZ_REST_DATE where ymd=cast(@startDate as int) or ymd=cast(@endDate as int))=2
and (select datediff(d,@startDate,@endDate))=(select count(*)from HCSZ_REST_DATE where ymd>cast(@startDate as int) and ymd<cast(@endDate as int))+1
)
set @re=0
else
begin
while(select count(*)from HCSZ_REST_DATE where ymd=cast(@startDate as int))>0
set @startDate=convert(char(8),dateadd(d,1,@startDate),112)
while(select count(*)from HCSZ_REST_DATE where ymd=cast(@endDate as int))>0
set @endDate=convert(char(8),dateadd(d,-1,@endDate),112)
set @re=datediff(d,@startDate,@endDate)-(select count(*)from HCSZ_REST_DATE where ymd>cast(@startDate as int)and ymd<cast(@endDate as int))
end
return @re*@intFlag
end


--测试语句:
select dbo.GetEndDateSubtractStartDate('20060127','20060213')
--结果6
select dbo.GetEndDateSubtractStartDate('20060128','20060205')
--结果0
select dbo.GetEndDateSubtractStartDate('20060128','20060206')
--结果0
select dbo.GetEndDateSubtractStartDate('20060128','20060213')
--结果5
回复
funsuzhou 2006-01-24
我的思路是如果开始日期和结束日期一样 或者 (开始日期、结束日期都是休息日 且 它们之间的跨日期天数= (>开始日期 并且 <结束日期 的休息天数)+1)
返回0

否则 让开始日期=它之后的第一个不是休息日的日期,结束日期=它之前的第一个不是休息日的日期,返回重新赋值后的开始日期、结束日期之间的跨日期天数- (>开始日期 并且 <结束日期 的休息天数)
回复
funsuzhou 2006-01-24
比如20060121 20060122是休息日,20060128~20060205是休息日,20060211 20060212是休息日
设开始日期是d1,结束日期是d2,则:
d1=20060127 d2=20060213 ->希望得到值:6
d1=20060128 d2=20060205 ->希望得到值:0
d1=20060128 d2=20060206 ->希望得到值:0
d1=20060128 d2=20060213 ->希望得到值:5


我自己编了个函数,因为这个问题对于生产型企业是很常用的,所以还请各位高手帮忙看看:
CREATE function dbo.GetEndDateSubtractStartDate (@startDate varchar(8),@endDate varchar(8))
returns int
as
begin
declare @intFlag int
set @intFlag=1
if(@startDate>@endDate)
begin
declare @temp varchar(8)
set @temp=@startDate
set @startDate=@endDate
set @endDate=@temp
set @intFlag=-1
end
declare @re int
if @startDate=@endDate or (
(select count(*)from HCSZ_REST_DATE where ymd=cast(@startDate as int) or ymd=cast(@endDate as int))=2
and (select datediff(d,@startDate,@endDate))=(select count(*)from HCSZ_REST_DATE where ymd>cast(@startDate as int) and ymd<cast(@endDate as int))+1
)
set @re=0
else
begin
while(select count(*)from HCSZ_REST_DATE where ymd=cast(@startDate as int))>0
set @startDate=convert(char(8),dateadd(d,1,@startDate),112)
while(select count(*)from HCSZ_REST_DATE where ymd=cast(@endDate as int))>0
set @endDate=convert(char(8),dateadd(d,-1,@endDate),112)
set @re=datediff(d,@startDate,@endDate)-(select count(*)from HCSZ_REST_DATE where ymd>cast(@startDate as int)and ymd<cast(@endDate as int))
end
return @re*@intFlag
end
回复
bugchen888 2006-01-23
还有哪里不对?
回复
funsuzhou 2006-01-23
后来想了一下,好像没这么简单。
请高手赐教!
回复
funsuzhou 2006-01-23
这样的话只需设一列就可以了->YMD
回复
funsuzhou 2006-01-23
对,感谢臭虫^_^这样一年的日历也就50条左右的记录
回复
-狙击手- 2006-01-23
TO:happyflystone(仙林幽谷客)
今天升星星啦

-------------


前天吧,呵呵





还有其它好方法吗?
-------------

特殊日期没有规律,比如停电,我哪知道什么时候啊
回复
bugchen888 2006-01-23
表的结构就那样设计,只是在表里只存放休息日的日期。

计算2006年任何两天之间扣除休息天的天数:

SELECT datediff(dd,'20060101','20060501') - COUNT(*)
FROM [table]
WHERE YMD>='20060101'
AND YMD<='20060501'
回复
小辉 2006-01-23
同意楼上的

另:
TO:happyflystone(仙林幽谷客)
今天升星星啦
回复
funsuzhou 2006-01-23
我也想到用表来做:
id int identity
YMD char(8)
flag bit
比如休息日和上班日用不同的标记
然后用id差再减去休息日的标记数目

还有其它好方法吗?
回复
-狙击手- 2006-01-23
特别日期可以用一个表来维护一下啊,查询时跳过就是了
回复
发动态
发帖子
MS-SQL Server
创建于2007-09-28

3.2w+

社区成员

MS-SQL Server相关内容讨论专区
申请成为版主
社区公告
暂无公告