【问题标题】:Oracle problems with CTECTE 的 Oracle 问题
【发布时间】:2020-06-16 16:54:03
【问题描述】:

我已经实施了您的更改并尝试进行更多更改。我的目标是更新 access_history 表并为这些记录设置处理 = 1,从而创建了一组 emp_attendance 记录。

当我尝试查找 MIN(ts) 和 MAX(ts) 时,出现以下错误

ORA-00937: 不是单组群函数

当我添加一个组时,我得到一个不同的错误。我发布了带有错误的代码,想知道您能否告诉我如何完成删除错误并在同一查询中发布更新。

-- 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;

【问题讨论】:

    标签: sql oracle syntax common-table-expression


    【解决方案1】:

    在下面的 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>
    

    【讨论】:

    • 非常感谢您的帮助。最初,我在 SELECT 上方有 INSERT 语句,并且收到缺少关键字 SELECT 的错误。然后我通过剪切和粘贴将代码移动到您放置它的位置,但我遇到了语法错误。毫无疑问,我错过了一些文字。我的清单上还有最后一个问题,希望得到您的专业知识。当更多数据添加到 access_history 表时,不再次重新处理相同记录的最佳方法是什么
    • 不客气。从不重新处理相同的记录开始,我想您应该包含 NOT EXISTS 子句。换句话说:插入表中不存在的行(还)。另一个选项是 NOT IN(这通常更容易理解)。
    • 很抱歉再次打扰您,但我希望您能看看我更新的问题。您的更改效果很好,但我需要更多功能并且遇到语法错误
    • 您所做的更改毫无意义。如果您不对它们做任何事情,为什么需要最小/最大 TS?我建议你从头开始——看看你在这些表中有什么,并确保你知道你想要什么结果。然后开始编码,一步一步来。
    • 我确实需要它们,因为行不断被添加到 access_history 表中。我想在 INSERT 完成后构造以下查询... update access_history set processed = 1 where ts >= min_ts and ts
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多