Sql 如何在单个表中应用合并

Sql 如何在单个表中应用合并,sql,oracle,sql-update,Sql,Oracle,Sql Update,我想使用合并更新我的表。因此,当一名员工加入另一家公司时,其新的加入日期将更新为其上一次入职时的离职日期。约束没有唯一的id和名称no、ename、dept、comp、doj、doe这些是表emp中的属性 这是我必须更新的表 Sno ENAME COMP DEPT DOJ DOE ----------------------------------------------- 1 rock mi it 10-AUG-18 - 2

我想使用合并更新我的表。因此,当一名员工加入另一家公司时,其新的加入日期将更新为其上一次入职时的离职日期。约束没有唯一的id和名称no、ename、dept、comp、doj、doe这些是表emp中的属性

这是我必须更新的表

Sno ENAME   COMP    DEPT    DOJ         DOE 
-----------------------------------------------
1   rock    mi      it  10-AUG-18    -  
2   dock    apple   it  12-AUG-18    -  
3   rock    google  it  01-AUG-70    -  
4   dock    samsung it  26-AUG-89    -  
应用合并后,它应该是这样的

Sno ENAME   COMP    DEPT    DOJ         DOE 
-----------------------------------------------
1   rock    mi      it  10-AUG-18    01-AUG-70  
2   dock    apple   it  12-AUG-18    26-AUG-89  
3   rock    google  it  01-AUG-70    -  
4   dock    samsung it  26-AUG-89    -

在这种情况下,您可以直接使用update,因为在这种情况下,merge语句可能会出现问题

UPDATE MYTABLE M1
SET M1.DOE = (SELECT DOJ FROM (SELECT M2.DOJ, 
ROW_NUMBER() OVER (PARTITION BY M2.ENAME ORDER BY M2.DOJ) AS RN 
FROM MYTABLE M2 
WHERE M1.ENAME = M2.ENAME
AND M1.COMP <> M2.COMP
AND M2.DOJ < M1.DOJ
) WHERE RN = 1)
此外,您还可以在UPDATE语句中使用WHERE子句来限制未更改其作业的记录或第一个作业中的记录,以避免使用NULL进行不必要的更新


干杯

您可以将“合并”与子查询一起使用:

merge into t using
      (select t.*, lead(doj) over (partition by ename order by doj) as next_doj
       from t
      ) tt
      on tt.sno = t.sno and tt.next_doj is not null
when matched then update
    set doe = next_doj;
您还可以使用子查询和更新来表达这一点:

您可以使用包含select语句的update语句,其中with..as子句包含lag over。。还有马克斯。。其分析函数的结果将用作嵌套select语句的匹配条件

update tab t2
   set t2.doe = ( with t1 as ( 
                         select t.*, 
                                lag(doj) over (partition by ename order by doj) as lg_doj,
                                max(doj) over (partition by ename order by doj) as mx_doj
                           from tab t
                    )  
                    select lg_doj
                      from t1
                     where t1.ename = t2.ename
                       and t1.mx_doj = t2.doj 
                     ); 

但不适合按员工姓名追踪员工,您应该改用员工ID。

根据您的代码,所有现有doe中的新doj都会更新为同一员工姓名Sno ENAME COMP DEPT doj doe 1 rock mi it 10-AUG-18 01-AUG-70 2 rock apple it 12-AUG-18 01-AUG-70 3 rock google it 01-AUG-70-应该更新为Sno ENAME COMP DEPT doj doe doe doe1 rock mi it 10-AUG-18 12-AUG-18 2 rock apple it 12-AUG-18 01-AUG-70 3 rock google it 01-AUG-70-从ORDER BY中删除DESC,并将>更改为<在最后一个条件中根据上述注释更新了答案。如果我必须使用源表和目标表,则使用merge.where初始目标表empty@TanmaySwami . . . 您将有一个不同的问题,insert将更合适。使用SELECT emp NO、ename、company、dept、doj、doe合并到emp1 x,从x上的emp y开始生效。enmae=y.ename匹配后,更新emp M1 SET M1.doe=从SELECT M2.doj选择doj,按M2.ename按M2.doj描述为RN的分区上的行数,其中M1.ename=M2.ename和M1.company M2.company和M2.doj>M1.doj,其中RN=1-1,如果不匹配,则插入编号、ename、company、dept、doj、doe、有效值SY.empno、y.company、y.dept、y.doj、y.doe、y.valid----我在匹配语句时遇到问题。@TanmaySwami。这个合并和这个答案有点不同。也许你应该问一个新问题。
update tab t2
   set t2.doe = ( with t1 as ( 
                         select t.*, 
                                lag(doj) over (partition by ename order by doj) as lg_doj,
                                max(doj) over (partition by ename order by doj) as mx_doj
                           from tab t
                    )  
                    select lg_doj
                      from t1
                     where t1.ename = t2.ename
                       and t1.mx_doj = t2.doj 
                     );