Вы можете преобразовать свои числовые (очевидно) начальные / конечные представления времени в доли дней или в интервалы и добавить их к преобразованной дате.Предположительно, вы действительно хотите, чтобы 240000 действительно были полуночью следующего дня, а не одной секунды до этого, если вы выполняете вычисления.Например, вы могли бы сделать:
select
date '1900-01-01'
+ floor("JDDate" / 1000) * interval '1' year
+ (mod("JDDate", 1000) -1) * interval '1' day
+ floor("START" / 10000) * interval '1' hour
+ floor(mod("START", 10000) / 100) * interval '1' minute
+ mod("START", 100) * interval '1' second
as start_datetime,
date '1900-01-01'
+ floor("JDDate" / 1000) * interval '1' year
+ (mod("JDDate", 1000) -1) * interval '1' day
+ case when "END" = 240000 then interval '1' day
else floor("END" / 10000) * interval '1' hour
+ floor(mod("END", 10000) / 100) * interval '1' minute
+ mod("END", 100) * interval '1' second
end
as end_datetime
from ccd021
where "JDDate" > 118000;
Расчеты в основном те же, но END
сохраняет выражение случая - он просто добавляет полный день для 240000 вместо установленного времени.
Если у вас есть дубликаты, которые вы хотите удалить (и по какой-то причине не можете удалить из базы данных), вы можете использовать distinct
.
select distinct ltrim(substr(nr, -6), '0') as staff_nr,
date '1900-01-01'
+ ...
Я бы предложил вам использоватьэти преобразования или что-то подобное, как основа для всех ваших элементов отображения - как только вы получите эти полные значения даты, вы можете отформатировать их как строки, как вам угодно.Например:
with cte (staff_nr, start_datetime, end_datetime) as (
select distinct ltrim(substr(nr, -6), '0'),
date '1900-01-01'
+ floor("JDDate" / 1000) * interval '1' year
+ (mod("JDDate", 1000) -1) * interval '1' day
+ floor("START" / 10000) * interval '1' hour
+ floor(mod("START", 10000) / 100) * interval '1' minute
+ mod("START", 100) * interval '1' second,
date '1900-01-01'
+ floor("JDDate" / 1000) * interval '1' year
+ (mod("JDDate", 1000) -1) * interval '1' day
+ case when "END" = 240000 then interval '1' day
else floor("END" / 10000) * interval '1' hour
+ floor(mod("END", 10000) / 100) * interval '1' minute
+ mod("END", 100) * interval '1' second
end
from ccd021
where "JDDate" > 118000
)
select staff_nr,
to_char(start_datetime, 'YYYY-MM-DD HH24:MI:SS') as start_datetime,
to_char(end_datetime, 'YYYY-MM-DD HH24:MI:SS') as end_datetime,
end_datetime - start_datetime as diff_in_days,
24 * (end_datetime - start_datetime) as diff_in_hours,
cast(end_datetime as timestamp) - cast(start_datetime as timestamp) as diff_as_interval
from cte
where end_datetime != start_datetime;
..., который также показывает фильтр для удаления строк, начало и конец которого совпадают.
db <> fiddle demo
(Ну, на самом деле, я бы посоветовал вам переосмыслить модель данных, но это кажется невозможным ... Даже если вы не можете заменить способ хранения данных, вы могли бы бытьвозможность добавлять дополнительные виртуальные столбцы для преобразованных значений, поэтому вам не нужно выполнять преобразование самостоятельно при запросе.)