Сократить дату до финансового года

Следующий вид базы данных усекает дату в финансовом году (1 апреля):

CREATE OR REPLACE VIEW FISCAL_YEAR_VW AS
SELECT
  CASE
    WHEN to_number(to_char(SYSDATE, 'MM')) < 4 THEN    
      to_date('1-APR-'||to_char(add_months(SYSDATE, -12), 'YYYY'), 'dd-MON-yyyy')
    ELSE
      to_date('1-APR-'||to_char(SYSDATE, 'YYYY'), 'dd-MON-yyyy')
  END AS fiscal_year
FROM
  dual;

Это позволяет нам рассчитать текущий финансовый год на основе сегодняшней даты.

Как можно упростить или оптимизировать эти вычисления?

Ответ 1

ADD_MONTHS(TRUNC(ADD_MONTHS(SYSDATE,-3),'YYYY'),3)

Ответ 2

Возможно, это...

SELECT to_date('01/04/' ||
to_char(extract(YEAR FROM SYSDATE)
- CASE WHEN extract(MONTH FROM SYSDATE) BETWEEN 1 AND 4 THEN 1 ELSE 0 END),
'DD/MM/YYYY') FROM dual;

Я думаю, это еще один вариант...

SELECT add_months(trunc(SYSDATE) - extract(DAY FROM SYSDATE) + 1,
- (extract(MONTH FROM SYSDATE) + CASE
WHEN extract(MONTH FROM SYSDATE) <= 4 THEN 12 ELSE 0 END) + 4)
FROM dual;

Другие параметры переписываются как функция, которая возвращает дату, или логика может быть упрощена, если вы можете просто вернуть номер года для текущего финансового года, так как вам понадобится только логика внутри to_char.

Ответ 3

TRUNC() может быть применимо к датам с использованием различных масок формата. Самое уместное, trunc(sysdate, 'yyyy') дает нам первый день года. Так что это даст нам 01-го апреля текущего года...

add_months(trunc(sysdate, 'yyyy'), 3)

и эта дата для предыдущего года...

add_months(trunc(add_months(sysdate, -12), 'yyyy'), 3)

Итак:

CREATE OR REPLACE VIEW FISCAL_YEAR_VW AS
WITH cte as 
    ( select add_months(trunc(sysdate, 'yyyy'), 3) as this_year
             , add_months(trunc(add_months(sysdate, -12), 'yyyy'), 3) as last_year
      from dual )
SELECT
  CASE
    WHEN SYSDATE >= cte.this_year THEN    
      cte.this_year
    ELSE
      cte.last_year
  END AS fiscal_year
FROM
  cte;

caveat: у меня еще не было возможности проверить этот код, чтобы он мог содержать опечатки. Я проверю его позже и при необходимости исправлю.

Ответ 4

Я считаю, что функция TO_CHAR (дата, 'Q') оракула очень полезна для расчета фискальных календарей. В нижеследующем запросе используется предложение "with" для создания двух вещей

  • Пример данных - таблица test_dates.
  • financial_map - простое сопоставление календарных кварталов с вашим фискальным календарем. В этом примере четвертый календарный квартал является 1-м финансовым кварталом (1 октября).

Пример:

with test_dates as (
 select sysdate + level * 80 test_date from dual connect by level < 11
),
fiscal_map as (
 select 1 cal, 2 fiscal from dual
 union
 select 2 cal, 3 fiscal from dual
 union
 select 3 cal, 4 fiscal from dual
 union
 select 4 cal, 1 fiscal from dual
)
select 
 test_date, 
 TO_CHAR(test_date, 'Q') cal_quarter, 
 fiscal_map.fiscal,
 (case when CAL < fiscal then 
     TO_CHAR(test_date, 'yyyy') + 0
     else TO_CHAR(test_date, 'yyyy') + 1
 end) FISCAL_YEAR
from test_dates, fiscal_map
where fiscal_map.cal = TO_CHAR(test_date, 'Q')
order by test_date

Вывод:

TEST_DT CAL_Q   FISCAL Q    FISCAL_YR
22-Jul-10   3   4   2010
10-Oct-10   4   1   2011
29-Dec-10   4   1   2011
19-Mar-11   1   2   2011
07-Jun-11   2   3   2011
26-Aug-11   3   4   2011
14-Nov-11   4   1   2012
02-Feb-12   1   2   2012
22-Apr-12   2   3   2012
11-Jul-12   3   4   2012

Ответ 5

select T.USERNAME,T.CREATED,

CASE WHEN EXTRACT (MONTH FROM T.CREATED)>=4 AND EXTRACT (MONTH FROM T.CREATED)<=12 THEN 
TO_CHAR(EXTRACT (YEAR FROM T.CREATED))||'-'||TO_CHAR(EXTRACT (YEAR FROM T.CREATED)+1)
  WHEN EXTRACT (MONTH FROM T.CREATED)<4 THEN 
TO_CHAR(EXTRACT (YEAR FROM T.CREATED)-1)||'-'||TO_CHAR(EXTRACT (YEAR FROM T.CREATED)) ELSE NULL END FY
from sys.dba_users t WHERE T.USERNAME in ('101655','100149')

Выход будет:

1   101655  14/01/2014 12:21:53 2013-2014
2   100149  05/05/2012 16:55:00 2012-2013