Oracle - формат и структура данных / запросов - PullRequest
0 голосов
/ 14 декабря 2018

Это моя первая неделя с SQL (Oracle).Я никогда раньше не использовал SQL.Только пытается понять запросы.В настоящее время я пытаюсь передать запрос, который я преобразовал до сих пор в Excel (power query), через SQL (Oracle) на стороне сервера, чтобы получить соответствующие улучшения производительности.Это означает, что я реализовал шаги в мощных запросах, пытаясь реализовать их с помощью оператора SQL.Я уже задавал несколько вопросов здесь, а также получил много помощи и хороших идей от вас.Я думаю, что имеет смысл разобраться со всем в рамках одного вопроса. Структура исходной таблицы или базы данных выглядит следующим образом:

Имя = Пример значения

  • JDDate = 118001
  • Элемент списка
  • START = 63000 (на 06:30:00)
  • END = 240000 (на 24:00:00)
  • NR = 34000001
  • Терминал = MM01X11
  • Деп = XX01
  • DOC = 1000800001
  • Тип = 1
  • Ключ 1 = 99000000
  • Key2 = 99000000

  • Сначала мне нужны все значения с "Typ" = 1 и JDDate => 118000

ГДЕ "JDDate"> 118000 И "Typ" = 1

  • Тогда мне нужно разность / временной шаг между START и END, основанный на правильном JDDate / Format.К сожалению, вот некоторые дубликаты, основанные на JDDate, START;КОНЕЦ;Terminal.:

.

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 "POOL0101"."9909KK"
WHERE   "JDDate" >118000
    AND "Typ" = 1

)
select staff_nr,
  to_char(start_datetime, 'YYYY-MM-DD HH24:MI:SS') as end_datetime,
  to_char(end_datetime, 'YYYY-MM-DD HH24:MI:SS') as end_datetime,
  end_datetime - start_datetime as diff_in_days
from cte
  • И, по крайней мере, у меня есть устаревшие данные / дубликаты в Key1 и Key2.Таким образом, Key1 содержит каждый раз число.Key2 содержит либо 0, либо число, которое также является номером в Key1.Если в Key1 и Key2 один и тот же номер, обе строки должны быть удалены.

Может ли кто-нибудь помочь мне включить все эти элементы в SQL?

Есть ли способ показать вам образцовую базу данных?

С наилучшими пожеланиями, Джошуа

1 Ответ

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

Есть ли способ показать вам примерную базу данных?

Вы можете использовать dbfiddle.uk для создания тестовых таблиц и запросов.Предположим, у вас есть следующая тестовая таблица (называемая ORIGINAL) и данные:

Таблица

create table original (
  jddate number
, starttime timestamp
, endtime timestamp
, nr number
, terminal varchar2( 100 )
, dep varchar2( 100 )
, doc number
, typ number
, key1 number
, key2 number 
) ;

INSERTs

insert into original
select 118001
, trunc( sysdate ) + ( 6/24 ) + ( 30/(24*60 ) )
, trunc( sysdate ) + (86399/86400)
, 34000001, 'MM01X11', 'XX01', 1000800001, 1, 99000000, 99000000  from dual union all 
-- duplicate
select 118001
, trunc( sysdate ) + ( 6/24 ) + ( 30/(24*60 ) )
, trunc( sysdate ) + (86399/86400)
, 34000001, 'MM01X11', 'XX01', 1000800001, 1, 99000000, 99111111  from dual union all 
select 118001
, trunc( sysdate ) + ( 6/24 ) + ( 30/(24*60 ) )
, trunc( sysdate ) + (86399/86400)
, 34000001, 'MM01X11', 'XX01', 1000800001, 1, 99000000, 99111111  from dual union all 
--
select 118001
, trunc( sysdate ) + ( 6/24 ) + ( 30/(24*60 ) )
, trunc( sysdate ) + (86399/86400)
, 34000001, 'MM01X11', 'XX01', 1000800001, 2, 99000000, 99000000  from dual union all 
select 118001
, trunc( sysdate ) + ( 6/24 ) + ( 30/(24*60 ) )
, trunc( sysdate ) + (86399/86400)
, 34000001, 'MM01X11', 'XX01', 1000800001, 3, 99000000, 99000000  from dual union all 
select 118001
, trunc( sysdate ) + ( 6/24 ) + ( 30/(24*60 ) )
, trunc( sysdate ) + (86399/86400)
, 34000001, 'MM01X11', 'XX01', 1000800001, 4, 99000000, 99000000  from dual ;

SELECT

-- select * from original;    
JDDATE  STARTTIME                     ENDTIME                       NR        TERMINAL  DEP   DOC         TYP  KEY1      KEY2      
    118001  15-DEC-18 06.30.00.000000000  15-DEC-18 23.59.59.000000000  34000001  MM01X11   XX01  1000800001  1    99000000  99000000  
    118001  15-DEC-18 06.30.00.000000000  15-DEC-18 23.59.59.000000000  34000001  MM01X11   XX01  1000800001  1    99000000  99111111  
    118001  15-DEC-18 06.30.00.000000000  15-DEC-18 23.59.59.000000000  34000001  MM01X11   XX01  1000800001  1    99000000  99111111  
    118001  15-DEC-18 06.30.00.000000000  15-DEC-18 23.59.59.000000000  34000001  MM01X11   XX01  1000800001  2    99000000  99000000  
    118001  15-DEC-18 06.30.00.000000000  15-DEC-18 23.59.59.000000000  34000001  MM01X11   XX01  1000800001  3    99000000  99000000  
    118001  15-DEC-18 06.30.00.000000000  15-DEC-18 23.59.59.000000000  34000001  MM01X11   XX01  1000800001  4    99000000  99000000  

Требования

{1} Сначала мне нужны все значения с "Typ" = 1 и JDDate => 118000

{2} Затем мне нужна разница / временной шаг между START и ENDоснованный на правильном JDDate / Format.К сожалению, вот некоторые дубликаты, основанные на JDDate, START;КОНЕЦ;Terminal.:

{3} И, по крайней мере, у меня есть некоторые устаревшие данные / дубликаты в Key1 и Key2.Таким образом, Key1 содержит каждый раз число.Key2 содержит либо 0, либо число, которое также является номером в Key1.Если в Key1 и Key2 одно и то же число, обе строки должны быть удалены.

Пример запроса - в качестве отправной точки (для предложения WHERE потребуется дополнительная работа ...)

select distinct                    -- {2} remove duplicates
  jddate
, endtime - starttime as interval_ -- {2} 
, nr
, terminal
, dep
, doc
, typ
, key1
, key2
from original 
where typ = 1 and jddate > 118000  -- {1}
  and key1 <> key2                 -- {3}
; 

-- result
JDDATE  INTERVAL_            NR        TERMINAL  DEP   DOC         TYP  KEY1      KEY2      
118001  +00 17:29:59.000000  34000001  MM01X11   XX01  1000800001  1    99000000  99111111 

Для преобразования значений в столбце JDDATE в Oracle DATE вы можете создать небольшую функцию, используя код ответа , который вы получили ранее.(Вам не нужно, но это уберет некоторый «беспорядок» из ваших SELECT), например,

--  /12111543/sql-data-zhylena-cyyddd-do-daty
/*
select date '1900-01-01'
  + floor(118001 / 1000) * interval '1' year
  + (mod(118001, 1000) - 1) * interval '1' day
from dual;
*/

-- this is far from perfect, needs range checking, exception handling etc
create or replace function cyyddd_to_date ( cyyddd number ) return date
is
begin
  return 
    date '1900-01-01' 
  + floor( cyyddd / 1000 ) * interval '1' year 
  + ( mod( cyyddd, 1000 ) - 1 ) * interval '1' day
  ;
end;
/

-- quick test
select 
  cyyddd_to_date( 118001 ) date_
, to_char( cyyddd_to_date( 118001 ), 'YYYY-MM-DD' ) datetime_
from dual; 

-- result
DATE_      DATETIME_   
01-JAN-18  2018-01-01

Окончательный запрос

select distinct                    -- {2} remove duplicates
  to_char( cyyddd_to_date( jddate ), 'YYYY-MM-DD' ) date_
, endtime - starttime  interval_   -- {2} 
, nr
, terminal
, dep
, doc
, typ
, key1
, key2
from original 
where typ = 1 and jddate > 118000  -- {1}
  and key1 <> key2                 -- {3}
; 

-- result
DATE_       INTERVAL_            NR        TERMINAL  DEP   DOC         TYP  KEY1      KEY2      
2018-01-01  +00 17:29:59.000000  34000001  MM01X11   XX01  1000800001  1    99000000  99111111 

Протестировано с Oracle 12c и Oracle 11g, dbfiddle здесь .

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