Oracle PL SQL Отрицательные минуты преобразуются в отрицательные ЧЧ:мм

В коде используется отрицательное или положительное целое число минут. Я успешно использую приведенный ниже код некоторое время, но затем понял, что если введенное количество минут меньше -60 (т.е. -15), возвращаемое значение чч: мм будет положительным, а не отрицательным. Я могу понять, почему это не работает, но изо всех сил пытаюсь придумать альтернативу. Обычно вводимые значения превышают 60 или -60, что всегда обеспечивает правильный знак значения часа.

Select nvl(-15,0) mins, decode(to_char(trunc(-15/60),'9999') || ':' ||ltrim(to_char(mod(abs(-15),60), '00')),':','00:00', to_char(trunc(-15/60),'9999') || ':' ||ltrim(to_char(mod(abs(-15),60), '00'))) hrs_mins from dual

Oracle PL SQL Отрицательные минуты преобразуются в отрицательные ЧЧ:мм

Я ожидаю/хочу увидеть -15 и -00:15

🤔 А знаете ли вы, что...
Oracle Database поддерживает множество операционных систем, включая Linux, Windows и многие другие.


40
2

Ответы:

Думаю, вам нужна еще одна проверка — является ли значение, которое вы передали этому фрагменту кода, положительным или отрицательным (см. строку № 7). Также я изменил модель формата с 9999 на 9900.

SQL> SELECT NVL (&&value, 0) mins,
  2         DECODE (
  3               TO_CHAR (TRUNC (&&value / 60), '9900')
  4            || ':'
  5            || LTRIM (TO_CHAR (MOD (ABS (&&value), 60), '00')),
  6            ':', '00:00',
  7               CASE WHEN &&value < 0 THEN '-' END
  8            || TO_CHAR (TRUNC (&&value / 60), 'FM9900')
  9            || ':'
 10            || LTRIM (TO_CHAR (MOD (ABS (&&value), 60), '00'))) hrs_mins
 11    FROM DUAL;
Enter value for value: -15

      MINS HRS_MINS
---------- ----------
       -15 -00:15

SQL> undefine value
SQL> /
Enter value for value: 25

      MINS HRS_MINS
---------- ----------
        25 00:25

SQL>

Решено

Гораздо проще:

with
  test_data (mins) as (
    select    10 from dual union all
    select    60 from dual union all
    select   150 from dual union all
    select     0 from dual union all
    select  null from dual union all
    select   -15 from dual union all
    select  -120 from dual union all
    select  -150 from dual union all
    select -1587 from dual
  )
select mins,
       to_char(sign(mins) * (trunc(abs(mins) / 60) + mod(abs(mins), 60) / 100)
              , 'fm99999990d00', 'nls_numeric_characters = :,') as hours_mins
from   test_data
;
 


      MINS HOURS_MINS  
---------- ------------
        10 0:10        
        60 1:00        
       150 2:30        
         0 0:00        
                       
       -15 -0:15       
      -120 -2:00       
      -150 -2:30       
     -1587 -26:27 

В вашей попытке вы конвертируете null в 0; если у вас есть веская причина для этого, вы можете сделать это и здесь. я этого не делал; в большинстве случаев null не означает (или не должен) означать «ноль».