DATEADD не возвращает правильные даты для некоторых строк - PullRequest
3 голосов
/ 21 мая 2019

Функция должна возвращать новую дату после текущей даты, и добавляется num_of_flows.Num_of_flows представляет собой целочисленное значение

ALTER  function [dbo].[M20_22_GetLoanMaturityDate_FIN_10]
(
    @AcctAcid varchar(50),
    @ScheduleNum varchar(50),
    @bank_id varchar(6) = '03'
)
returns varchar(50)
as 
BEGIN
    Declare @lMaturityDate varchar(50)
    begin
            select @lMaturityDate = 
            case Finacle_Lrs.LR_FREQ_TYPE   
                             when 'W' then  dateadd(day, (Finacle_Lrs.NUM_OF_FLOWS - 1) * 7,Finacle_Lrs.FLOW_START_DATE)
                             when 'F' then  dateadd(day, (Finacle_Lrs.NUM_OF_FLOWS - 1) * 14,Finacle_Lrs.FLOW_START_DATE)
                             when 'M' then  (dateadd(month, Finacle_Lrs.NUM_OF_FLOWS - 1, Finacle_Lrs.FLOW_START_DATE))
                             when 'Q' then  (dateadd(month, (Finacle_Lrs.NUM_OF_FLOWS - 1) * 3, Finacle_Lrs.FLOW_START_DATE))
                             when 'H' then  dateadd(month, (Finacle_Lrs.NUM_OF_FLOWS - 1) * 6, Finacle_Lrs.FLOW_START_DATE)
                             when 'Y' then  dateadd(month, (Finacle_Lrs.NUM_OF_FLOWS - 1) * 12, Finacle_Lrs.FLOW_START_DATE)
                      end
            from    [TEST_EIMDW_Archive].[ARCHOWN].[FINCL10_LRS] Finacle_Lrs
            where   Finacle_Lrs.acid = @AcctAcid
            and Finacle_Lrs.shdl_num = @ScheduleNum
            and Finacle_Lrs.FLOW_ID in ('PRDEM','EIDEM')
            AND Finacle_Lrs.ACTIVE_FLAG = 'Y' AND Finacle_Lrs.DELETE_FLAG= 'N'
            and Finacle_Lrs.bank_id = @bank_id
            and Finacle_Lrs.FLOW_START_DATE = ( select max(a.FLOW_START_DATE)
                            from   [TEST_EIMDW_Archive].[ARCHOWN].[FINCL10_LRS] a
                            where  a.ACID = Finacle_Lrs.ACID
                                and    a.SHDL_NUM = Finacle_Lrs.SHDL_NUM
                            and    a.FLOW_ID in ('PRDEM', 'EIDEM') AND a.ACTIVE_FLAG = 'Y' AND a.DELETE_FLAG='N' and a.bank_id = @bank_id
        );
end
        return isnull(@lMaturityDate,null);

END

После некоторых проверок я заметил, что 19629 строк преуменьшаются за один день при сравнении исходного кода в базе данных оракула.Пожалуйста, ознакомьтесь с версионной версией кода:

FUNCTION GetLoanMaturityDate(AcctAcid VARCHAR2, ScheduleNum VARCHAR2) RETURN DATE IS
        lMaturityDate DATE;
    BEGIN
        begin
            select decode(lrs.LR_FREQ_TYPE, 'W', lrs.FLOW_START_DATE + (lrs.NUM_OF_FLOWS - 1) * 7,
                            'F', lrs.FLOW_START_DATE + (lrs.NUM_OF_FLOWS - 1) * 14,
                            'M', add_months(lrs.FLOW_START_DATE, lrs.NUM_OF_FLOWS - 1) ,
                            'Q', add_months(lrs.FLOW_START_DATE, (lrs.NUM_OF_FLOWS - 1) * 3),
                            'H', add_months(lrs.FLOW_START_DATE, (lrs.NUM_OF_FLOWS - 1) * 6),
                            'Y', add_months(lrs.FLOW_START_DATE, (lrs.NUM_OF_FLOWS - 1) * 12)
                     )
            into    lMaturityDate
            from    lrs
            where   lrs.acid = AcctAcid
            and lrs.shdl_num = ScheduleNum
            and lrs.FLOW_ID in ('PRDEM','EIDEM')
            and lrs.FLOW_START_DATE = ( select max(a.FLOW_START_DATE)
                            from   lrs a
                            where  a.ACID = lrs.ACID
                                and    a.SHDL_NUM = lrs.SHDL_NUM
                            and    a.FLOW_ID in ('PRDEM', 'EIDEM')
                               ) ;
        exception
            when no_data_found then
                lMaturityDate:=NULL;
        end;

        return lMaturityDate;
    END GetLoanMaturityDate;

Также вот запрос сравнения, который я выполнил, чтобы увидеть неправильные строки:

SELECT eim.acid as eim_acid,it.[ACID] as it_acid,
eim.[MATURITY_DATE] as eim_maturity_date,it.[MATURITY_DATE] as it_maturity_date ,
eim.[DAYS_TO_MATURITY] as eim_DAYS_TO_MATURITY,it.[DAYS_TO_MATURITY] as it_DAYS_TO_MATURITY,(it.[DAYS_TO_MATURITY]-eim.[DAYS_TO_MATURITY]) as diff
FROM [TEST_EIMDW_BOJ_REPORTS].[BOJOWN].[loans_maturity_profile] eim 
inner join [dbo].[IT_LOANS_MATURITY_PROFILE] it on eim.acid= it.acid
where eim.MATURITY_DATE != it.MATURITY_DATE 

Наконец, ниже приведен результат запроса, показывающий сравнениеправильный набор результатов, который я сейчас пытаюсь исправить на сервере sql:

enter image description here

Ответы [ 3 ]

2 голосов
/ 22 мая 2019

Просто добавьте к тому, что сказал Гордон, точное поведение функции ADD_MONTHS в Oracle заключается в том, что если исходная дата является последним днем ​​его месяца, то возвращаемая дата также является последним днем ​​результирующего месяца (независимо отдлина месяца исходной даты).

SQL Server не имеет аналогичной функции.

Какая реализация правильная или имеет значение, зависит от ваших конкретных обстоятельств.

2 голосов
/ 21 мая 2019

Oracle add_months() и SQL Server dateaddd(month) имеют разную семантику, особенно в конце месяца.

Итак:

select add_months(date '2019-02-28', 1)
from dual

--> 2019-03-31

(см. db <>fiddle )

Принимая во внимание:

select dateadd(month, 1, '2019-02-28')

--> 2019-03-28

(см. db <> fiddle )

Это может быть немного сложно эмулироватьПоведение Oracle в SQL Server.Я даже не уверен, желательно ли это.

0 голосов
/ 22 мая 2019

SQL Server «Конец месяца» - функция EOMONTH (start_date [, month_to_add]) будет вести себя подобно ORACLE add_months в последний день месяца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...