有没有更优雅的方式来重复使用代码块?

时间:2018-08-31 12:57:55

标签: sql oracle

我喜欢像下面那样编写我的sql。

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

例如我写了2次 current_year 而不是 extract(从sys_date年起)

另一个例子,我写了两次 first_of_april_this_year 而不是 to_date('01 .APR。'|| current_year ||'00:00:00','DD.MON.YYYY HH24:MI:SS')

它可以工作,但是正如您在下面看到的那样,它不是非常漂亮/易于阅读。您是否有更好的建议,而我又不会因为不必在多个地方修复某些东西而使它更具可读性而从中受益呢?我也使用了从句,但是恕我直言,它的可读性更低。非常感谢你! <3

PS:让我们在这里继续讨论重用代码块的话题,而不是深入研究如何以可测试的方式找到4月1日以前的特定任务可以做得更好。 TY!

-- 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 个答案:

答案 0 :(得分:3)

您可以使用子查询分解(aka Common Table Expressions,又名CTE)来简化具有多个子查询的查询。例如。您的查询将变为:

Promise#all

顺便说一句,根据日期计算4月1日可以更简单:

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;

在这里,我们从指定日期返回3个月,将结果日期截断到该年(直到该年的1月1日),然后再加上3个月,将我们带到该年的4月1日。

答案 1 :(得分:1)

您可以使用子查询分解(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

答案 2 :(得分:0)

您可以做的更短:

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