代码之家  ›  专栏  ›  技术社区  ›  David

Firebird calc在日期之间跳过周末

  •  0
  • David  · 技术社区  · 7 年前

    我想将此sql代码转换为firebird sql,用于查找两个日期之间的工作日:

    CREATE FUNCTION [dbo].fn_CountWeekDays
    (
    @fromdate Datetime,
    @todate Datetime
    )
    RETURNS TABLE AS RETURN
    (
    
     SELECT
    (DATEDIFF(dd, @fromdate, @todate) + 1)
    -(DATEDIFF(wk, @fromdate, @todate) * 2)
    -(CASE WHEN DATENAME(dw, @fromdate) = 'Sunday' THEN 1 ELSE 0 END)
    -(CASE WHEN DATENAME(dw, @todate) = 'Saturday' THEN 1 ELSE 0 END)
    As NoOfWeekDays
    
    )
    

    谢谢

    1 回复  |  直到 7 年前
        1
  •  1
  •   Mark Rotteveel    3 年前

    您当前的SQL Server函数是一个表值函数(它返回一个表),Firebird 3(及更早版本)中最接近的等效函数是一个可选择的存储过程:

    create or alter procedure CountWeekDays(fromdate timestamp, todate timestamp)
    returns (NoOfWeekDays bigint)
    as
    declare normalizedFrom timestamp;
    declare normalizedTo timestamp;
    begin
        normalizedFrom = dateadd(-1 * extract(weekday from fromdate) day to fromdate);
        normalizedTo = dateadd(-1 * extract(weekday from todate) day to todate);
        NoOfWeekDays = (DATEDIFF(day, fromdate, todate) + 1)
                -(DATEDIFF(week, normalizedFrom , normalizedTo) * 2)
                -(CASE WHEN extract(weekday from fromdate) = 0 THEN 1 ELSE 0 END)
                -(CASE WHEN extract(weekday from todate) = 6 THEN 1 ELSE 0 END);
        -- Suspend is necessary to make it selectable!
        suspend;
    end
    

    从…起 datediff(week ...) Firebird不计算周数,但计算两个日期之间7天的周期,例如 datediff(week, date'2017-07-14', date'2017-07-20') (星期五到下一个星期四)为0,而不是1。将标准化为一周的星期日将确保正确计算周差。

    考虑到数据的性质,您也可以在SQL Server中使用标量函数。标量函数的等价物是 PSQL function (在Firebird 3中介绍)

    create or alter function fn_CountWeekDays(fromdate timestamp, todate timestamp)
    returns bigint
    as
    declare normalizedFrom timestamp;
    declare normalizedTo timestamp;
    begin 
        normalizedFrom = dateadd(-1 * extract(weekday from fromdate) day to fromdate);
        normalizedTo = dateadd(-1 * extract(weekday from todate) day to todate);
        return (DATEDIFF(day, fromdate, todate) + 1)
                -(DATEDIFF(week, normalizedFrom , normalizedTo) * 2)
                -(CASE WHEN extract(weekday from fromdate) = 0 THEN 1 ELSE 0 END)
                -(CASE WHEN extract(weekday from todate) = 6 THEN 1 ELSE 0 END);
    end