【问题标题】:Calculation of date in function函数中日期的计算
【发布时间】:2014-10-22 10:43:52
【问题描述】:
   1      28/11/2011 ...

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

【问题讨论】:

    标签: sql sql-server date


    【解决方案1】:

    你可以在 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');
    

    【讨论】:

    • 如果 EndDate 可以说是 20/10/2013 并且我的 BaseDate(在 RecursiveCTE 被调用之后)是 16/10/2013 那么函数应该在考虑到 20/10/2013 之后停止。它不应该将 7 添加到 2013 年 10 月 16 日。我是否也需要检查日期之间的间隔
    • 我添加了一个涵盖这个的新脚本
    • 感谢您的回复。但它应该将 4 添加到 16/10/2013 它必须考虑数据库中的所有日期,在这种情况下它是 20/10/2013。我需要一个函数,这样我就可以在用 Visual Studio C# 编写的 sql 查询中使用函数名。我不确定,但我猜在 SQL 中我们需要编写 CREATE FUNCTION Funtionname 来声明一个函数
    • 要创建一个函数,这与您所说的差不多,但请注意我添加的评论,说明由于长期存在的错误,这在 SQL Server 中是多么的痛苦。我已经更新了我的答案,以展示如何创建一个函数并应对包含结束日期的新要求。
    • 感谢它工作得很好,但我只需要返回计数器。当计算第一个 7 天间隔时,计数器应该是 1 下一个 7 天计数器应该是 2,下一个 7 天计数器应该是 3 所以等等。我不想归还整张桌子
    【解决方案2】:

    试试这个 - 它将获取所有周数并在子查询中分配一个行号。然后只选择行号 = 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]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-10
      • 1970-01-01
      相关资源
      最近更新 更多