计算功能中的日期

时间:2014-10-22 10:43:53

标签: sql sql-server date

   1      28/11/2011 ...

如何在SQL中编写函数来实现上述模式?

2 个答案:

答案 0 :(得分:2)

您可以在SQL Server中执行以下操作:

DECLARE @BaseDate DATE = '20111107';
DECLARE @EndDate DATE = GETDATE(); --Or the "end of dates in the database"
WITH RecursiveCTE AS (
    SELECT
        1 AS [Counter],
        @BaseDate AS [MyDate]
    UNION ALL
    SELECT
        [Counter] + 1,
        DATEADD(DAY, 7, MyDate)
    FROM
        RecursiveCTE
    WHERE
        MyDate < @EndDate)
SELECT * FROM RecursiveCTE OPTION (MAXRECURSION 0);

要处理不准确的日期并将其转换为函数,您可以执行此操作:

--Function definition
CREATE FUNCTION SuperDuperDataCalculator (
    @BaseDate DATE = '20131016',
    @EndDate DATE = '20131020')
RETURNS @Results TABLE (
    [Counter] INT,
    [Date] DATE)
AS
BEGIN
    WITH RecursiveCTE AS (
        SELECT
            1 AS [Counter],
            @BaseDate AS [MyDate]
        UNION ALL
        SELECT
            [Counter] + 1,
            CASE WHEN DATEADD(DAY, 7, MyDate) > @EndDate THEN @EndDate ELSE DATEADD(DAY, 7, MyDate) END
        FROM
            RecursiveCTE
        WHERE
            MyDate < @EndDate)
    INSERT INTO
        @Results
    SELECT * FROM RecursiveCTE OPTION (MAXRECURSION 0);
    RETURN;
END;
GO

--Usage
SELECT * FROM SuperDuperDataCalculator('20131016', '20131020');

--Results
Counter Date
1   2013-10-16
2   2013-10-20

请注意,我们必须使用多语句表值函数,因为SQL Server中存在一个错误,它不允许您在简单的表值函数中使用OPTION。另一种方法是从函数中删除OPTION(MAXRECURSION 0)并记住每次引用它时都使用它(即一个相当差的替代方法)。

...最后,如果你想只返回最大计数器值,你可以将其重写为标量值函数,即:

--Function definition
CREATE FUNCTION SuperDuperDataCalculator (
    @BaseDate DATE = '20131016',
    @EndDate DATE = '20131020')
RETURNS INT
AS
BEGIN
    DECLARE @Results TABLE (
    [Counter] INT,
    [Date] DATE);
    DECLARE @ReturnValue INT;
    WITH RecursiveCTE AS (
        SELECT
            1 AS [Counter],
            @BaseDate AS [MyDate]
        UNION ALL
        SELECT
            [Counter] + 1,
            CASE WHEN DATEADD(DAY, 7, MyDate) > @EndDate THEN @EndDate ELSE DATEADD(DAY, 7, MyDate) END
        FROM
            RecursiveCTE
        WHERE
            MyDate < @EndDate)
    INSERT INTO
        @Results
    SELECT * FROM RecursiveCTE OPTION (MAXRECURSION 0);
    SELECT @ReturnValue = MAX([Counter]) FROM @Results;
    RETURN @ReturnValue;
END;
GO
SELECT dbo.SuperDuperDataCalculator('20131016', '20131020');

答案 1 :(得分:0)

试试这个 - 它将获得所有周并在子查询中分配一个rownumber。然后只选择行号= 1的记录,因为该周可能会有更多结果。因此RowNo = 1

 SELECT ROW_NUMBER() OVER(ORDER BY RowNo) AS IncrementalWeek,dte
 FROM 
 (
      SELECT DISTINCT DATEPART(ww,CONVERT(VARCHAR(20),createdDate,111)) AS [week],
                      CONVERT(VARCHAR(20),createdDate,111) AS dte,
                      ROW_NUMBER() OVER(PARTITION BY DATEPART(ww,Convert(VARCHAR(20),createdDate,111)) ORDER BY DATEPART(ww,CONVERT(VARCHAR(20),createdDate,111))) AS RowNo 
      FROM YourTable

 ) AS tble
WHERE RowNo = 1
ORDER BY [week]