【问题标题】:Truncate date to fiscal year将日期截断为会计年度
【发布时间】:2011-02-10 08:30:40
【问题描述】:

以下数据库视图将日期截断为财政年度(4 月 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;

这使我们可以根据今天的日期计算当前会计年度。

如何简化或优化此计算?

【问题讨论】:

    标签: sql oracle oracle11g truncate


    【解决方案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 中的逻辑。

      【讨论】:

      • 查询结果不同。您提供的代码今天返回 2009-04-01。它应该返回 2010-04-01。
      【解决方案3】:

      TRUNC() 可以有效地应用于日期,具有不同的格式掩码。最相关的是,trunc(sysdate, 'yyyy') 给了我们一年中的第一天。所以这将为我们提供当年的 01-APR ...

      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;
      

      警告:我还没有机会测试此代码,因此它可能包含拼写错误。稍后我会测试它并在必要时更正它。

      【讨论】:

        【解决方案4】:

        我发现 oracle 的 TO_CHAR(date, 'Q') 功能对于计算财政日历非常有用。下面的查询使用 'with' 子句来构建两件事

        1. 样本数据 - test_dates 表。
        2. fiscal_map - 日历季度到您的会计日历的简单映射。在此示例中,第 4 个日历季度是第一个财政季度(10 月 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
          

          【讨论】:

            猜你喜欢
            • 2016-02-25
            • 1970-01-01
            • 2021-03-07
            • 1970-01-01
            • 2022-08-03
            • 1970-01-01
            • 1970-01-01
            • 2013-06-04
            • 2016-11-11
            相关资源
            最近更新 更多