如何在Sql 2005中编写Excel附带的YearFrac函数?
答案 0 :(得分:5)
使用DateDiff找出两个日期之间的距离,然后将该值除以365
修改强>
当然,您可以创建自己的功能来完成这项工作:
create function yearfrac (@d1 datetime, @d2 datetime) returns float
as
begin
return abs(datediff(d, @d1, @d2)) / 365.00
end
答案 1 :(得分:3)
对于默认用法(两个数据参数):
datediff(day, date1, date2) / 360.0
对于第三个参数值为3的特殊情况:
datediff(day, date1, date2) / 365.0
编辑:
添加了一个小数,使其成为浮点运算。
答案 2 :(得分:0)
我还为此创建了一个函数。 但是,当将函数应用于大集合时,最好将函数移至实际查询,而不要使用函数。
/*
Yearfrac
Purpose: calculate the fraction of years between start_date and end_date
Code Actual/actual is translated from VBA code Excel formula YearFrac
Basis Day count basis
0 or omitted US (NASD) 30/360
1 Actual/actual
2 Actual/360
3 Actual/365
4 European 30/360
*/
ALTER FUNCTION [obm].[fn_YearFrac]
(
@Start_date DATE
, @End_date DATE
, @Basis INT
)
RETURNS DECIMAL(18, 10)
AS
BEGIN
DECLARE @YearFrac DECIMAL(18, 10)
;
if @Basis = 1
begin
SELECT @YearFrac =
datediff(d, @Start_date, @End_date) /
case when -- Scenario 1: Jaar start = Jaar eind
year(@Start_date) = year(@End_date)
then
a.aantal_dagen
when -- Scenario 2: Kalenderjaar van eiddatum is 1 jaar na kalenderjaar startdatum
year(@End_date) - year(@Start_date) = 1
then
b.aantal_dagen
when -- Scenario 3: Kalenderjaar van eiddatum is meer dan 1 jaar na kalenderjaar startdatum
year(@End_date) - year(@Start_date) > 1
then
(c.aantal_dagen/c.aantal_jaar)
else null
end
from (select @Start_date dat_start, @End_date dat_end) src
cross apply (select cast ( COUNT(nbr_jaar) as decimal(18,10) ) aantal_dagen from dbo.dim_datum icd where icd.nbr_jaar = year(src.dat_start)) a
cross apply (select cast ( COUNT(nbr_jaar) + 365 as decimal(18,10) ) aantal_dagen from dbo.dim_datum icd where nbr_maand = 2 and nbr_dag_in_maand = 29 and cast( dat_datum as date ) between dat_start and dat_end) b
cross apply (select cast ( COUNT(nbr_jaar) as decimal(18,10) ) aantal_dagen, count(distinct nbr_jaar) aantal_jaar from dbo.dim_datum icd where nbr_jaar between year(dat_start) and year(dat_end) ) c
end
if @Basis = 2
begin
SELECT @YearFrac = DATEDIFF (d, @start_date, @end_date) / 360.00
end
if @Basis = 3
begin
SELECT @YearFrac = DATEDIFF (d, @start_date, @end_date) / 365.00
end
RETURN
@YearFrac;
END;
答案 3 :(得分:-3)
我知道这是一个有点迟到的回应,但万一其他人偶然发现这是我做过的事情:
CREATE FUNCTION dbo.udfYearFrac
(
@StartDate AS DATETIME,
@EndDate AS DATETIME
)
RETURNS DECIMAL(18,6)
AS
BEGIN
DECLARE @YearFrac AS DECIMAL(18,6)
DECLARE @nbDaysInPeriod AS INT
DECLARE @nbYears AS INT
SELECT
@nbDaysInPeriod = DATEDIFF(DAY, @StartDate, @EndDate)
,@nbYears = YEAR(@EndDate) - YEAR(@StartDate) + 1
SELECT @YearFrac = @nbDaysInPeriod /
CASE WHEN YEAR(@StartDate) = YEAR(@EndDate) OR (YEAR(@EndDate)-1 = YEAR(@StartDate) AND (MONTH(@StartDate) > MONTH(@EndDate) OR MONTH(@StartDate) = MONTH(@EndDate) AND (DAY(@StartDate) >= DAY(@EndDate))))
THEN
CASE WHEN YEAR(@StartDate) = YEAR(@EndDate) AND ISDATE(CAST(YEAR(@StartDate) AS CHAR(4)) + '0229') = 1
THEN 366.0
ELSE
CASE WHEN DAY(@EndDate) = 29 AND MONTH(@EndDate) = 2
THEN 366.0
ELSE
CASE WHEN ISDATE(CAST(YEAR(@StartDate) AS CHAR(4)) + '0229') = 1
THEN
CASE WHEN (@StartDate <= cast('2/29/' + cast(YEAR(@StartDate) AS CHAR(4)) AS DATETIME) AND cast('2/29/' + cast(YEAR(@StartDate) AS CHAR(4)) AS DATETIME) <= @EndDate)
THEN 366.0
ELSE 365.0
END
ELSE
CASE WHEN ISDATE(CAST(YEAR(@EndDate) AS CHAR(4)) + '0229') = 1
THEN
CASE WHEN (@StartDate <= cast('2/29/' + cast(YEAR(@EndDate) AS CHAR(4)) AS DATETIME) AND cast('2/29/' + cast(YEAR(@EndDate) AS CHAR(4)) AS DATETIME) <= @EndDate)
THEN 366.0
ELSE 365.0
END
ELSE 365.0
END
END
END
END
ELSE
((@nbYears * 365.0) +
(
SELECT COUNT(*) FROM
(
SELECT (ROW_NUMBER() OVER(ORDER BY TABLE_NAME ASC) - 1) * 4 + 1900 AS [YEAR]
FROM INFORMATION_SCHEMA.COLUMNS
) yr
WHERE [YEAR] BETWEEN YEAR(@StartDate) AND YEAR(@EndDate)
)
) / @nbYears
END
RETURN @YearFrac
END