日期:2014-05-18  浏览次数:20618 次

SQL Server2008设计一个函数的问题
我想设计一个函数,实现功能是输入日期和天数,返回具体的工作日日期(工作日不包括周六、周日、节假日),例如输入日期:201203,天数:10,返回工作日日期是20120314。
我现在的问题是节假日不知道该怎样去判断??
我目前的思路是创建一个节日表,我把国家通告的放假时间都输入进去了,然后通过这个表去判断节假日,但具体SQL不知道怎样去实现?
这是基础数据源码:(我输入了2年节日信息)
SQL code

USE tempdb;
GO
IF OBJECT_ID('furlough') IS NOT NULL
DROP TABLE furlough;
GO
/*创建节日表*/
CREATE TABLE furlough
(id INT IDENTITY(1,1),--节日ID
 fname VARCHAR(20) ,--节日名称
 FurloughStarttime DATETIME,--开始放假时间
 FurloughEndtime DATETIME, --结束放假时间
 updatetime datetime --更新时间
 );
-- 添加数据
INSERT INTO dbo.furlough VALUES  ('元旦','20120101','20120103',GETDATE());
INSERT INTO dbo.furlough VALUES  ('春节','20120122','20120128',GETDATE());
INSERT INTO dbo.furlough VALUES  ('清明节','20120402','20120404',GETDATE());
INSERT INTO dbo.furlough VALUES  ('劳动节','20120429','20120501',GETDATE());
INSERT INTO dbo.furlough VALUES  ('端午节','20120622','20120624',GETDATE());
INSERT INTO dbo.furlough VALUES  ('国庆节','20120930','20121007',GETDATE());
INSERT INTO dbo.furlough VALUES  ('元旦','20121230','20130101',GETDATE());
INSERT INTO dbo.furlough VALUES  ('春节','20130209','20130215',GETDATE());
INSERT INTO dbo.furlough VALUES  ('清明节','20130404','20130406',GETDATE());
INSERT INTO dbo.furlough VALUES  ('劳动节','20130429','20130501',GETDATE());
INSERT INTO dbo.furlough VALUES  ('端午节','20130610','20130612',GETDATE());
INSERT INTO dbo.furlough VALUES  ('中秋节','20130919','20120921',GETDATE());
INSERT INTO dbo.furlough VALUES  ('国庆节','20131001','20131007',GETDATE());
GO
IF TYPE_ID('tyWorkday') IS NOT NULL 
DROP TYPE tyWorkday;
GO
 /*工作日日期*/
 CREATE TYPE tyWorkday AS TABLE 
 (Id INT IDENTITY(1,1),
  Workday DATETIME);


这个是我设计的函数,只是判断了周六周日外的日期,节假日还没判断:
SQL code

IF OBJECT_ID('fnWorkday') IS NOT NULL
DROP FUNCTION fnWorkday;
GO
CREATE FUNCTION fnWorkday
(@date INT ,
 @n INT )
RETURNS DATETIME
AS 
BEGIN
  DECLARE @m INT ,--增长的天数
          @d INT ,--当月的天数
          @wdate VARCHAR(10), --工作日期
          @tyw AS tyWorkday,
          @workday DATETIME --需要返回的工作日期
  SET @m=1;
  SET @wdate=@date*100+@m;
  SET @d=DATEDIFF(DAY,@wdate,DATEADD(MONTH,1,@wdate ));
  WHILE @m<=@d
    BEGIN
        SET @wdate=@date*100+@m;
        /*当日期不是周六、周日的时候插入到@tyw表*/
        IF DATEPART(dw,@wdate) NOT IN (1,7)
          BEGIN
               INSERT INTO @tyw VALUES(@wdate);              
          END;
        SET @m=@m+1;  
    END;
  SELECT @workday=Workday FROM @tyw WHERE Id=@n;
  RETURN @workday;
END;




------解决方案--------------------
--定义节假日表
CREATE TABLE tb_Holiday(
HDate smalldatetime primary key clustered, --节假日期
Name nvarchar(50) not null) --假日名称
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDay]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_WorkDay]
GO

--计算两个日期之间的工作天数
CREATE FUNCTION f_WorkDay(
@dt_begin datetime, --计算的开始日期
@dt_end datetime --计算的结束日期
)RETURNS int
AS
BEGIN
IF @dt_begin>@dt_end
RETURN(DATEDIFF(Day,@dt_begin,@dt_end)
+1-(
SELECT COUNT(*) FROM tb_Holiday
WHERE HDate BETWEEN @dt_begin AND @dt_end))
RETURN(-(DATEDIFF(Day,@dt_end,@dt_begin)
+1-(
SELECT COUNT(*) FROM tb_Holiday
WHERE HDate BETWEEN @dt_end AND @dt_begin)))
END
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDayADD]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_WorkDayADD]
GO

--在指定日期上增加工作天数
CREATE FUNCTION f_WorkDayADD(
@date datetime, --基础日期
@workday int --要增加的工作日数
)RETURNS datetime
AS
BEGIN
IF @workd