YearFrac в Sql 2005 - PullRequest
       12

YearFrac в Sql 2005

5 голосов
/ 10 июля 2009

Как мне написать функцию YearFrac, которая поставляется с Excel в SQL 2005?

Ответы [ 4 ]

5 голосов
/ 10 июля 2009

Найдите расстояние между двумя датами, используя DateDiff , а затем разделите это значение на 365

EDIT

Конечно, вы можете создать свою собственную функцию для выполнения работы:

create function yearfrac (@d1 datetime, @d2 datetime) returns float
as
begin
return abs(datediff(d, @d1, @d2)) / 365.00
end
3 голосов
/ 10 июля 2009

Для использования по умолчанию (два параметра данных):

datediff(day, date1, date2) / 360.0

Для особого случая, когда третий параметр имеет значение 3:

datediff(day, date1, date2) / 365.0

Edit:
Добавлена ​​десятичная дробь, чтобы сделать ее операцией с плавающей запятой.

0 голосов
/ 20 сентября 2018

Я также создал функцию для этого. Однако, когда функция применяется к большому набору, лучше переместить функцию к реальному запросу, чем использовать функцию.

/*
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;
0 голосов
/ 25 мая 2017

Я знаю, что ответ немного опоздал, но на тот случай, если кто-нибудь еще наткнется на это, вот что я сделал:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...