SQL UDF返回日期数组

时间:2014-07-23 03:09:55

标签: sql-server sql-function

我目前编写了一个小型UDF(表值类型),用于在开始日期和结束日期之间返回table个日期。已经从另一个表中检索了开始日期和结束日期。

Start_End_Table
WeekNumber | Start Date | End Date

功能:

CREATE FUNCTION [dbo].[DatesBetween](@startDate datetime, @endDate datetime)
RETURNS @dates TABLE (
   DateValue datetime NOT NULL
) 
AS
BEGIN
   WHILE (@startDate <= @endDate) BEGIN
      INSERT INTO @dates VALUES (@startDate);
      SET @startDate = DATEADD(day, 1, @startDate);
   END;

   RETURN;
END;

到目前为止,我一直以下列方式使用此功能,

SELECT * FROM [dbo].[DatesBetween](@startDate datetime, @endDate datetime);

继续我需要从Start_End_Date表开始,结束日期并调用该函数。因此,我不认为返回table是一个选项。如何让这个函数返回一个日期数组而不是一个表?或者还有其他方法可以把它包起来吗?

1 个答案:

答案 0 :(得分:2)

尝试CROSS APPLY,因为它将为JOINed表中的每一行运行函数:

SELECT [Date Value]
FROM dbo.Start_End_Table dates
CROSS APPLY [dbo].[DatesBetween](dates.StartDate, dates.EndDate)
WHERE [Week Number]=@WeekNumber;

示例输出类似于开始日期= 2014年1月1日,结束日期= 1/3/2014,@ weeknumber = 1:

 | DateValue
  1/1/2014
  1/2/2014
  1/3/2014

SQL Fiddle

修改
请尝试以下内联表值函数,因为它会比您的多行TVF快得多,因为:

  1. 内联TVF固有地比多线TVF更快
  2. 它是基于集合而不是依赖于WHILE循环
  3. -

    CREATE FUNCTION dbo.GetDates(@StartDate DATETIME, @EndDate DATETIME)
    RETURNS TABLE
    AS RETURN
    WITH cte AS
    (
        SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS [RowNum]
        FROM sys.objects WITH (NOLOCK)
    )
    SELECT DATEADD(DAY, (cte.[RowNum] - 1), @StartDate) AS [DateValue]
    FROM cte
    WHERE cte.[RowNum] < (DATEDIFF(DAY, @StartDate, @EndDate) + 2);
    GO
    
    SELECT * FROM dbo.GetDates('1/1/2014', '1/3/2014');