Oracle - объедините метку времени с датой и удалите дубликаты - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть БД Oracle, которая дает мне метку времени и дату в нескольких столбцах.

«JDDate» в качестве даты, «END» в качестве времени окончания и «START» в качестве начала.

Таким образом, дата выводится в формате CYYDDD, а время - в формате ЧЧММСС.С помощью следующей инструкции я получаю необходимые форматы:

SELECT
    DATE '1900-01-01' + FLOOR("JDDate" / 1000) * INTERVAL'1' YEAR+ (MOD("JDDate", 1000) -1) * INTERVAL'1' DAY AS "Date",
    LTRIM((SUBSTR("NR", -6)), '0') AS "Staff Nr",
    CASE WHEN "END" =240000 THEN '23:59:59' ELSE REPLACE(TO_CHAR("END", '00,00,00'),',',':') END AS "tEnd",
    REPLACE(TO_CHAR("START", '00,00,00'),',',':') AS "tStart",

FROM "POOLXX1"."CCD021"
WHERE   "JDDate" >118000

Теперь я хочу как-то получить разницу.Возможно, вам нужно объединить дату с отметкой времени и рассчитать разницу соответственно.Есть условие.Если для каждого человека (столбец «NR») на один день назначены одинаковые начальная и конечная отметки, то это дубликаты.Это следует игнорировать соответственно.Может быть, имеет смысл использовать их раньше.

Вам нужна дополнительная информация?

С уважением!Joshua

1 Ответ

0 голосов
/ 13 декабря 2018

Вы можете преобразовать свои числовые (очевидно) начальные / конечные представления времени в доли дней или в интервалы и добавить их к преобразованной дате.Предположительно, вы действительно хотите, чтобы 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

(Ну, на самом деле, я бы посоветовал вам переосмыслить модель данных, но это кажется невозможным ... Даже если вы не можете заменить способ хранения данных, вы могли бы бытьвозможность добавлять дополнительные виртуальные столбцы для преобразованных значений, поэтому вам не нужно выполнять преобразование самостоятельно при запросе.)

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