代码之家  ›  专栏  ›  技术社区  ›  Peter

有没有更优雅的方法来重用代码块?

  •  3
  • Peter  · 技术社区  · 7 年前

    好处是我可以重用多次使用的代码块,当我修复某个东西时,我总是只需要在一个地方修复它。

    我写了两遍 本年 而不是 摘录(从系统日期算起的年份)

    另一个例子,我写了两次 而不是 截止日期('01.APR.'年月日HH24:MI:SS')

    它是有效的,但正如你在下面看到的,它不是很漂亮/容易阅读。你有更好的建议,我不失去的好处,从来没有固定在多个地方的东西,但使它更可读?我也用了with从句,但我觉得那更不可读。非常感谢你!<3级

    -- gives the latest 1st of April based on sysdate, whereas for testing sysdate can freely be set     
    select 
        case when sys_date <= first_of_april_this_year then first_of_april_last_year else first_of_april_this_year end previous_first_of_april
        -- ,params3.* 
    from (    
        select 
            to_date ('01.APR.'|| current_year    ||' 00:00:00', 'DD.MON.YYYY HH24:MI:SS') first_of_april_this_year,
            to_date ('01.APR.'||(current_year-1) ||' 00:00:00', 'DD.MON.YYYY HH24:MI:SS') first_of_april_last_year,
            params2.*
        from (
            select 
                extract (year from sys_date) current_year,
                params1.* 
            from
            (select 
                to_date ('02.AUG.2018 00:00:01', 'DD.MON.YYYY HH24:MI:SS') sys_date  -- for testing, sysdate can be overwritten
                --sysdate sys_date 
            from dual) params1 
        ) params2 
    ) params3;
    
    3 回复  |  直到 7 年前
        1
  •  3
  •   Boneist    7 年前

    您可以使用子查询分解(又名公共表表达式,又名CTE)使包含多个子查询的查询更易于阅读。例如,您的查询将变成:

    WITH params1 AS (SELECT to_date('02.AUG.2018 00:00:01', 'DD.MON.YYYY HH24:MI:SS') sys_date -- for testing, sysdate can be overwritten
                     --sysdate sys_date 
                     FROM   dual),
         params2 AS (SELECT extract(YEAR FROM sys_date) current_year,
                            sys_date
                     FROM   params1),
         params3 AS (SELECT to_date('01.APR.' || current_year || ' 00:00:00', 'DD.MON.YYYY HH24:MI:SS') first_of_april_this_year,
                            to_date('01.APR.' || (current_year - 1) || ' 00:00:00', 'DD.MON.YYYY HH24:MI:SS') first_of_april_last_year,
                            sys_date
                     FROM   params2)
    SELECT CASE
             WHEN sys_date <= first_of_april_this_year THEN
              first_of_april_last_year
             ELSE
              first_of_april_this_year
           END previous_first_of_april
    FROM   params3;
    

    SELECT add_months(TRUNC(add_months(SYSDATE, -3), 'yyyy'), 3)
    FROM   dual;
    

    在这里,我们从指定日期返回3个月,将结果日期截短到年份(以获得当年的1月1日),然后简单地加上3个月,将我们带到当年的4月1日。

        2
  •  0
  •   MT0    7 年前

    您可以使用子查询分解( WITH )那么:

    • 您可以为子查询指定有意义的名称;以及
    • 您可以在子查询的标题中指定所有列名,以便将它们分组在一起(如果您有特别长的值列表,甚至可以在子查询的主体中添加相同的别名)。

    这样地:

    WITH current_date ( sys_date ) AS (
      SELECT TO_DATE( '02.AUG.2018 00:00:01', 'DD.MON.YYYY HH24:MI:SS' )
      FROM   DUAL
    ),
    financial_year_boundaries ( first_of_april_this_year, first_of_april_last_year, sys_date ) AS (
      SELECT ADD_MONTHS( TRUNC( sys_date, 'YYYY' ), 3 ),
             ADD_MONTHS( TRUNC( sys_date, 'YYYY' ), 3 - 12 ),
             sys_date
      FROM   current_date
    )
    SELECT CASE
           WHEN sys_date < first_of_april_this_year
           THEN first_of_april_last_year
           ELSE first_of_april_this_year
           END AS previous_first_of_april
    FROM   financial_year_boundaries
    
        3
  •  0
  •   Radagast81    7 年前

    WITH params1 AS (SELECT to_date('02.JAN.2011 00:00:01', 'DD.MON.YYYY HH24:MI:SS') sys_date -- for testing, sysdate can be overwritten sysdate sys_date 
                     FROM   dual)
    SELECT TO_DATE('04'||TO_CHAR(EXTRACT(YEAR FROM sys_date) - CASE WHEN EXTRACT(MONTH FROM sys_date) < 4 THEN 1 ELSE 0 END), 'MMRRRR') AS previous_first_of_april
      FROM params1