Есть ли более элегантный способ повторно использовать блоки кода? - PullRequest
0 голосов
/ 31 августа 2018

Мне нравится писать мой sql, как показано ниже.

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

например. Я пишу 2 раза current_year вместо extract (год от sys_date) .

Другой пример, я пишу 2 раза first_of_april_this_year вместо to_date ('01 .APR. '|| current_year ||' 00:00:00 ',' DD.MON.YYYY HH24 : MI: SS ')

.

Это работает, но, как вы можете видеть ниже, это не очень красиво / легко читается. Есть ли у вас лучшие предложения, когда я не теряю преимущества того, что мне никогда не придется что-то исправлять в нескольких местах, но делаю это более читабельным? Я также использовал with-предложения, но IMHO, это еще менее читабельно. Большое спасибо! <3 </p>

PS: Давайте, пожалуйста, остановимся на теме повторного использования блоков кода здесь, а не углубляться в то, как эта конкретная задача по поиску предыдущего 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 голосов
/ 31 августа 2018

Вы можете использовать предложения подфакторинга (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
0 голосов
/ 31 августа 2018

Вы можете сделать это еще короче:

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
0 голосов
/ 31 августа 2018

Вы можете использовать Факторинг подзапроса (также известные как Common Table Expressions или 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;

Кроме того, отработка 1-го апреля на основе даты может быть сделана проще:

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

Здесь мы возвращаемся на 3 месяца от указанной даты, усекаем результирующую дату до года (чтобы получить 1 января этого года), а затем просто добавляем 3 месяца назад, чтобы перенести нас на 1 апреля этого года.

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