Firebird calc之间的日期跳过周末

时间:2017-07-14 23:40:43

标签: sql firebird firebird-3.0

我想将这个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 个答案:

答案 0 :(得分:1)

您当前的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函数的输出进行了比较,并且我没有使用时间组件进行测试,您可能希望对其进行更多验证彻底。

鉴于数据的性质,您还可以在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

参考文献: