【问题标题】:How to apply merge in single table如何在单个表中应用合并
【发布时间】:2019-09-05 10:09:58
【问题描述】:

我想使用合并更新我的表。因此,当员工加入另一家公司时,其新的(加入日期)将在他之前的条目中更新为(退出日期)。约束(((there is no unique id and name)))(((sno, 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    -

【问题讨论】:

    标签: sql oracle sql-update


    【解决方案1】:

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

    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;
    

    您也可以使用子查询和update 来表达这一点:

    update t
        set doe = (select min(t2.doe)
                   from t tt
                   where tt.ename = t.ename and
                         tt.doe > t.doe
                  );
    

    【讨论】:

    • 如果我必须使用源表和目标表使用合并。
    • 最初目标表为空的地方
    • @TanmaySwami 。 . .你会有不同的问题,insert 会更合适。
    • MERGE INTO emp1 x USING (SELECT empno, ename, company, dept, doj, doe, valid FROM emp) y ON (x.enmae = y.ename) WHEN MATCHED THEN UPDATE emp M1 SET M1 .doe = (SELECT doj FROM (SELECT M2.doj, ROW_NUMBER() OVER (PARTITION BY M2.ename ORDER BY M2.doj DESC) AS RN FROM emp M2 WHERE M1.ename = M2.ename AND M1.company M2 .company AND M2.doj > M1.doj ) WHERE RN = 1) - 1 WHEN NOT MATCHED THEN INSERT(empno, ename, company, dept, doj, doe, valid) VALUES(y.empno, y.ename, y.公司,y.dept,y.doj,y.doe,y.valid); --------我在匹配语句时遇到问题。
    • @TanmaySwami 。 . . merge 与此答案中的内容有些不同。也许你应该问一个新问题。
    【解决方案2】:

    您可以使用update 语句,包括select 语句和with..as 子句,其中包含lag() over (..)max() 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 
                         ); 
    

    Demo

    但不适合通过员工姓名跟踪员工,您应该使用员工 ID。

    【讨论】:

      【解决方案3】:

      这种情况下你可以直接使用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 子句来限制没有更改其工作的记录或第一个工作的记录,以避免使用空值进行不必要的更新。

      干杯!!

      【讨论】:

      • 根据您的代码,新的 doj 在所有现有 doe 中更新(对于相同的员工姓名) 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 1 rock mi it 10-AUG-18 12-AUG-18 2 rock apple它 12-AUG-18 01-AUG-70 3 摇滚谷歌它 01-AUG-70 -
      • 从 ORDER BY 中删除 DESC 并将 > 更改为
      • 根据上面的评论更新了答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多