Рассчитайте разницу во времени между двумя столбцами varchar2, которые имеют время в формате ЧЧ.ММ - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь рассчитать разницу во времени между временем входа и выхода.

при использовании приведенного ниже кода он дает неверные данные.

(SELECT round(24 * (to_date(SIGN_OUT_TIME,'hh24:mi') - 
to_date(SIGN_IN_TIME,'hh24:mi')),2) diff_hours
FROM XXBCT.XXBCT_BIO_OTL_ENTRIES_SUMMARY
WHERE EMPLOYEE_NUMBER='112319'
AND attendance_dt    ='04-Jan-19');

Результат должен быть 08.13, но он дает 8.22

Ответы [ 3 ]

0 голосов
/ 27 марта 2019

Для разницы во времени у Oracle есть тип данных, он называется interval:

http://www.oracletutorial.com/oracle-basics/oracle-interval/

Oracle предоставляет вам два типа данных даты и времени: DATE и TIMESTAMP для хранения данных на определенный момент времени. Кроме того, он предоставляет тип данных INTERVAL, который позволяет хранить периоды времени.

Для меня это тот способ, которым я предпочитаю работать с разницей во времени, поскольку он сохраняет все громоздкие вычисления, которые в противном случае требуются при работе только с датами. «Хитрость» в приведенном ниже запросе заключается в том, что я конвертирую одну дату в метку времени с помощью to_timestamp. timestamp минус date дает вам interval взамен:

with 
first_date_vc2   as (select                '01:00' val from dual),
second_date_vc2  as (select                '09:13' val from dual),
first_date_date  as (select to_date(val,'HH24:MI') val from first_date_vc2),
second_date_date as (select to_date(val,'HH24:MI') val from second_date_vc2)
select 
    to_timestamp(sdd.val)-fdd.val 
from first_date_date fdd,second_date_date sdd;

-- TO_TIMESTAMP(SDD.VAL)-FDD.VAL
-- +00 08:13:00.000000

Включая желаемое форматирование вывода:

with 
first_date_vc2   as (select                '01:00'        val from dual),
second_date_vc2  as (select                '09:13'        val from dual),
first_date_date  as (select to_date(val,'HH24:MI')        val from first_date_vc2),
second_date_date as (select to_date(val,'HH24:MI')        val from second_date_vc2),
interval_between as (select to_timestamp(sdd.val)-fdd.val val from first_date_date fdd,second_date_date sdd)
select 
    extract( hour from val)||':'||extract( minute from val) val
from interval_between;

-- VAL
-- 8:13

Как уже указывал комментатор, фактический необходимый запрос будет зависеть от требований, таких как, может ли он быть более 24 часов или он может быть выполнен в полночь.

0 голосов
/ 27 марта 2019

8 часов 13 минут = 8,22 часа

Если вы просто хотите, чтобы число с частью единиц в качестве часов и дробной частью в минутах, вы можете взять дробную часть своего ответа и умножить ее0.6:

Настройка Oracle :

CREATE TABLE XXBCT_BIO_OTL_ENTRIES_SUMMARY (
  EMPLOYEE_NUMBER, ATTENDANCE_DT, SIGN_IN_TIME, SIGN_OUT_TIME
)
AS
SELECT '112319',
       DATE '2019-01-04',
       TO_CHAR( TIMESTAMP '2019-01-04 00:00:00', 'HH24:MI' ),
       TO_CHAR( TIMESTAMP '2019-01-04 08:13:00', 'HH24:MI' )
FROM   DUAL

Запрос :

SELECT ROUND( diff_hours, 2 ) AS diff_hours,
       TRUNC( diff_hours ) + MOD( diff_hours, 1 ) * 0.60 AS diff_hours_hhmi
FROM   (
  SELECT 24 * (to_date(SIGN_OUT_TIME,'hh24:mi') - to_date(SIGN_IN_TIME,'hh24:mi'))
           AS diff_hours
  FROM   XXBCT_BIO_OTL_ENTRIES_SUMMARY
  WHERE  EMPLOYEE_NUMBER = '112319'
  AND    attendance_dt   = DATE '2019-01-04'
);

Вывод:

DIFF_HOURS | DIFF_HOURS_HHMI
---------: | --------------:
      8.22 |            8.13

Вы также можете использовать INTERVAL тип данных:

SELECT TO_TIMESTAMP(SIGN_OUT_TIME,'hh24:mi') - TO_TIMESTAMP(SIGN_IN_TIME,'hh24:mi') AS diff_hours_interval,
       SUBSTR(TO_TIMESTAMP(SIGN_OUT_TIME,'hh24:mi') - TO_TIMESTAMP(SIGN_IN_TIME,'hh24:mi'), 12, 5 ) AS diff_hours_interval_string
FROM   XXBCT_BIO_OTL_ENTRIES_SUMMARY
WHERE  EMPLOYEE_NUMBER = '112319'
AND    attendance_dt   = DATE '2019-01-04';
DIFF_HOURS_INTERVAL           | DIFF_HOURS_INTERVAL_STRING
:---------------------------- | :-------------------------
+000000000 08:13:00.000000000 | 08:13                     

db <> fiddle здесь

0 голосов
/ 27 марта 2019

8,22 - разница в часах. 0,22 не минуты. Это часть целого часа. это соответствует ожидаемым 13 минутам.

Вот один из способов сделать это лучше. Вы получаете diffenrez в считанные секунды а затем вы можете получить часы, минуты и секунды, если хотите

select TO_CHAR(TRUNC(diff_seconds/3600),'FM9900') || '.' ||
       TO_CHAR(TRUNC(MOD(diff_seconds,3600)/60),'FM00') || '.' ||
       TO_CHAR(MOD(diff_seconds,60),'FM00')
  from (SELECT round(24 * 60 * 60 (to_date(SIGN_OUT_TIME,'hh24:mi') 
                                 - to_date(SIGN_IN_TIME,'hh24:mi')),2) diff_seconds
          FROM XXBCT.XXBCT_BIO_OTL_ENTRIES_SUMMARY
          WHERE EMPLOYEE_NUMBER='112319'
          AND attendance_dt    ='04-Jan-19'
        );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...