两个日期之间的SQL表值用户定义函数

时间:2015-05-26 11:44:58

标签: sql sql-server sql-server-2008

我需要使用两个参数构建一个表值用户定义函数 输入如select * from func_1('01/01/2012','09/09/2015');

输出应该是:

month quator semi_annual annual 
 1     1      1            2012
 2     1      1            2012
 3     1      1            2012
 4     2      1            2012
 5     2      1            2012
 6     2      1            2012
 7     3      2            2012
 .     .       .            ...
 .     .      .             ....

      upto 
9       3    2             2015

我需要一个表值函数。

我试过这样的代码

create function func3_D_D
(@startDate date, @endDate date)
RETURNS @dates table
(months int,quatorly int,Semi_anuual int,Annual int)
As
Begin 
declare
@months int,
@quatorly int,
@Semi_anuual int,
@Annual int;




select @months= DATEDIFF(MONTH, @startDate, @endDate);
select @quatorly= DATEDIFF(QUARTER, @startDate, @endDate);
select @Semi_anuual= DATEDIFF(QUARTER, @startDate, @endDate)/ 2;
select @Annual= DATEDIFF(YEAR, @startDate, @endDate);

WHILE (@endDate > @startDate) 

begin
insert into @dates
select @months,@quatorly,@Semi_anuual,@Annual;
End;
return;
End;

3 个答案:

答案 0 :(得分:0)

使用循环可以获得很好的性能。你需要为这种类型的东西使用计数表。你需要开始思考而不是逐行思考。一旦你有一个计数表(我在这里用cte生成),这很简单。

create function MyFunctionThatGetsDatesByRange
(
    @StartDate DATE
    , @EndDate DATE
) RETURNS TABLE WITH SCHEMABINDING AS RETURN
    WITH
        E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
        E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
        E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
        cteTally(N) AS 
        (
            SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
        )

    select DATEADD(DAY, N - 1, @StartDate) as date
        , DATEPART(MONTH, DATEADD(DAY, N - 1, @StartDate)) as Month
        , DATEPART(QUARTER, DATEADD(DAY, N - 1, @StartDate)) as Quarter
        , CASE when DATEPART(QUARTER, DATEADD(DAY, N - 1, @StartDate)) <= 2 then 1 else 2 end as SemiAnnual
        , DATEPART(YEAR, DATEADD(DAY, N - 1, @StartDate)) as Annual
    from cteTally
    where N <= DATEDIFF(DAY, @StartDate, @EndDate);

GO

declare @StartDate date = '2012-01-01'
    , @EndDate date = '2015-09-09';

select *
from dbo.MyFunctionThatGetsDatesByRange(@StartDate, @EndDate)   

答案 1 :(得分:0)

非常感谢您的回复,我通过使用以下代码获得了答案。

create function func5_D_D
(@startDate date, @endDate date)
RETURNS @dates table
(months int,
quators int,
semi_annual int,
annual int)
As
Begin 

WHILE @startDate <= @endDate
BEGIN

 INSERT INTO @dates(months,quators,semi_annual,annual) values (MONTH(@startDate), datepart(qq,@startDate),
 case when datepart(qq,@startDate) in (1,2) then 1 else
 2 End,datepart(yyyy,@startdate))

 SET @startDate = DATEADD(MONTH,1,@startDate)

 END
return;
end;

答案 2 :(得分:0)

X年Y个月和Z天中的两个日期之间的差异(例如:年,月和日中的年龄) 我们可以使用下面的脚本来获取年,月和日中两个日期之间的差。

X年Y个月和Z天中的两个日期之间的差异(例如:年,月和日中的年龄) 我们可以使用如下脚本来获取两个

之间的区别
datDECLARE @FromDate DATETIME = '2010-01-01 23:59:59.000', 
        @ToDate   DATETIME = '2015-01-02 00:00:00.000',
        @Years INT, @Months INT, @Days INT, @tmpFromDate DATETIME
SET @Years = DATEDIFF(YEAR, @FromDate, @ToDate)
 - (CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @FromDate, @ToDate),
          @FromDate) > @ToDate THEN 1 ELSE 0 END) 


SET @tmpFromDate = DATEADD(YEAR, @Years , @FromDate)
SET @Months =  DATEDIFF(MONTH, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SET @tmpFromDate = DATEADD(MONTH, @Months , @tmpFromDate)
SET @Days =  DATEDIFF(DAY, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(DAY, DATEDIFF(DAY, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SELECT @FromDate FromDate, @ToDate ToDate, 
       @Years Years,  @Months Months, @Days Days
s in Years, Months and days.