Oracle проблем с CTE - PullRequest
       19

Oracle проблем с CTE

0 голосов
/ 16 июня 2020

Я внес ваши изменения и пытаюсь внести еще несколько. Моя цель - выпустить обновление в таблице access_history и установить обработанное = 1 для тех записей, которые создали набор записей emp_attendance.

Когда я пытаюсь найти MIN (ts) и MAX (ts), я получить следующую ошибку

ORA-00937: не функция одногрупповой группы

Когда я добавляю группу, я получаю другую ошибку. Я разместил код с ошибкой, и мне было интересно, можете ли вы сказать мне, как выполнить sh удаление ошибки и выполнить обновление в том же запросе.

-- Drop table emp_info purge:
-- Drop table locations purge;
-- Drop table access_histoty purge;
-- Drop table emp_attendance purge;

ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';

CREATE TABLE employees
(
   employee_id NUMBER(6),
   first_name VARCHAR2(20),
   last_name VARCHAR2(25) NOT NULL,
   card_num varchar2(10)  NOT NULL
);

ALTER TABLE employees
     ADD ( CONSTRAINT employee_id_pk
   PRIMARY KEY (employee_id));


Insert into employees values (1, 'Mike', 'Jones', 'AAA1');

Insert into employees values (2, 'Jane', 'Doe', 'BBB2');


Insert into employees values (3, 'Paul', 'Smith', 'CCC3');

Insert into employees values (4, 'John', 'Henry', 'DDD4');



 Create table locations(
   location_id NUMBER(4),
   location_name varchar2(30),
   location_type char(1));

 -- A=access T=Time & Attendance 

ALTER TABLE locations 
     ADD ( CONSTRAINT lication_id_pk
   PRIMARY KEY (location_id));



Insert into locations values (101, 'South Front Door 1', 'T');

  Insert into locations values (102, 'South Front Door 2', 'T');

  Insert into locations values (103, 'East Back Door 1', 'T');

   Insert into locations values (104, 'East Back Door 2', 'T');

   Insert into locations values (105,'Computer Room', 'A');

   Insert into locations values (106,'1st Floor North',  'A');


Create table access_history(
   employee_id NUMBER(6), 
   card_num varchar2(10),
   location_id number(4),
   Access_date date,
   ts timestamp default systimestamp,
   processed NUMBER(1) default 0
);


INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (1, 'AAA1', 101,    TO_DATE('06212020 21:02:04',  'MMDDYYYY HH24:MI:SS'));


   -- TYpe T no previous data for this
   -- empid record INSERT empid, 
    -- start  time ONLY in table below 
     -- and  update last_start_date  
     -- with DATETIME.



INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (1, 'AAA1', 102,    TO_DATE('06212020 23:52:14',  'MMDDYYYY HH24:MI:SS'));


  -- Type T record empid, start_time
  --  set update end_time only in
  -- emp_attendance.



INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (2, 'BBB2', 103,    TO_DATE('06212020 08:32:35',  'MMDDYYYY HH24:MI:SS'));


 -- TYpe T  INSERT empid, start 
 -- time ONLY in emp_attendance.  
 -- update last_start_date with 
 --  DATETIME on emp_info table



INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (2, 'BBB2', 102,    TO_DATE('06212020 15:39:05',  'MMDDYYYY HH24:MI:SS'));


-- Type T record empid, start_time 
--  set, update end_time only in
-- emp_attendance.


INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (3, 'CCC3', 103,    TO_DATE('06212020 15:39:05',  'MMDDYYYY HH24:MI:SS'));


 -- TYpe T  INSERT empid, start 
 -- time ONLY in emp_attendance.  
 -- update last_start_date with 
 --  DATETIME on emp_info table



INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (3, 'CCC3', 105,    TO_DATE('06212020 18:19:55',  'MMDDYYYY HH24:MI:SS'));


-- Type A record don't do anything to 
-- emp_attendance.



INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (4, 'DDD4', 102,    TO_DATE('06212020 08:49:35',  'MMDDYYYY HH24:MI:SS'));

--  single record with no pair. Set
-- end_date to start_date if end_date
-- is NULL



INSERT INTO access_history
( employee_id, card_num,
   location_id, Access_date )
 VALUES (3, 'CCC3', 104,    TO_DATE('06222020 04:04:35',  'MMDDYYYY HH24:MI:SS'));


-- Type T record empid, start_time 
--  set, update end_time only in
-- emp_attendance.


 CREATE TABLE  emp_attendance    
  (seq_num NUMBER(10),
   employee_id NUMBER(6),
   start_date DATE,
   end_date DATE,
   create_date DATE DEFAULT SYSDATE
   );

   Create sequence emp_attendance_seq;

   insert into emp_attendance.   
     (seq_num, 
       employee_id, 
       start_date, 
      end_date)

   with

   -- error capturing min,max ts
   --
   prep (min_ts, max_ts, employee_id, start_date, rn, end_date) as (

     select MIN(ts), MAX(ts), employee_id, access_date

        , row_number()      over (partition by card_num order by access_date)

      , lead(access_date) over (partition by card_num order by access_date)

   from   access_history

 where  location_id in ( select location_id

                     from   locations

                      where  location_type = 'T'

                  )

                  AND processed = 0

  )

   select emp_attendance_seq.nextval,

      employee_id,

     start_date,

   nvl(end_date, start_date)

  from prep

 where  mod(rn, 2) = 1;

1 Ответ

1 голос
/ 16 июня 2020

В приведенном ниже CTE я пытаюсь ВСТАВИТЬ записи из SELECT в таблицу emp_attendance, но я не могу работать.

Будет легче помочь, если вы описали, что не так с ваша попытка. Потому что в нем просто отсутствует оператор INSERT INTO, вызов последовательности и функция NVL - по крайней мере, я так понял.

SQL> insert into emp_attendance (seq_num, employee_id, start_date, end_Date)
  2  with
  3    prep (employee_id, start_date, rn, end_date) as (
  4      select employee_id, access_date
  5           , row_number()      over (partition by card_num order by access_date)
  6           , lead(access_date) over (partition by card_num order by access_date)
  7      from   access_history
  8      where  location_id in ( select location_id
  9                          from   locations
 10                          where  location_type = 'T'
 11                        )
 12    )
 13  select emp_attendance_seq.nextval,
 14         employee_id,
 15         start_date,
 16         nvl(end_date, start_date)
 17  from prep
 18  where  mod(rn, 2) = 1;

4 rows created.

SQL> select * From emp_attendance;

   SEQ_NUM EMPLOYEE_ID START_DATE          END_DATE
---------- ----------- ------------------- -------------------
         1           1 21.06.2020 21:02:04 21.06.2020 23:52:14
         2           2 21.06.2020 08:32:35 21.06.2020 15:39:05
         3           3 21.06.2020 15:39:05 22.06.2020 04:04:35
         4           4 21.06.2020 08:49:35 21.06.2020 08:49:35

SQL>
...