比较同一个表中两个ID之间的行,并为该ID插入缺少的行

时间:2018-05-19 05:18:12

标签: sql oracle oracle11g

我有一张桌子,其结构如下所述 让我们说表名 - > TAB1

id   c1     c2    c3         c4
1    a      b   01-02-18     c          row1
1    o      b   01-02-18     c          row2
1    a      b   04-05-16     c          row3
1    n      g   01-02-18     d          row4
2    a      b   01-02-18     c          row5

所以我想将id 1行插入id 2.因为row1和row5的数据对于列c1,c2,c3,c4是相同的所以我想跳过要为id 2插入的row1。

表应如下所示

id   c1     c2    c3         c4
1    a      b   01-02-18     c          row1
1    o      b   01-02-18     c          row2
1    a      b   04-05-16     c          row3
1    n      g   01-02-18     d          row4
2    a      b   01-02-18     c          row5
2    o      b   01-02-18     c          row6
2    a      b   04-05-16     c          row7
2    n      g   01-02-18     d          row8

我写了这个查询,但没有给我预期的结果

用于根据列选择唯一记录:

select Count(*) FROM tab1 A
WHERE   Not EXISTS 
(select * from  tab1  B where  A.c1 = B.c1 AND A.c2 = B.c2 AND A.c3= B.c3 
AND A.c4 = B.c4 
and B.id=2 )and A.id = 1;

用于插入记录

insert into rsk_mdl_sec_map_ts
select '2', c1, c2, c3, c4
FROM tab1 A
WHERE   Not EXISTS 
(select * from  tab1  B where  A.c1 = B.c1 AND A.c2 = B.c2 AND A.c3= B.c3 
AND A.c4 = B.c4 
and B.id=2 )and A.id = 1;

任何人都可以帮助解决这个问题,或者建议我采取其他方法来实现同样的目标。谢谢

4 个答案:

答案 0 :(得分:0)

首先构建一个查询,选择应该被插入的行,并省略那些已经存在为id=2的行:

SELECT * 
FROM tab1 t1
WHERE id = 1
  AND NOT EXISTS (
    SELECT 'anything' FROM tab1 t2
    WHERE t1.c1=t2.c1
      AND t1.c2=t2.c2
      AND t1.c3=t2.c3
      AND t1.c4=t2.c4
      AND id = 2
)

| ID | C1 | C2 |                    C3 | C4 |
|----|----|----|-----------------------|----|
|  1 |  o |  b | 2018-01-02 00:00:00.0 |  c |
|  1 |  a |  b | 2016-04-05 00:00:00.0 |  c |
|  1 |  n |  g | 2018-01-02 00:00:00.0 |  d |

演示:http://sqlfiddle.com/#!4/d66fc/4

接下来,使用INSERT ... SELECT ....命令,只需将INSERT置于SELECT命令之上,并使用2常量作为ID,并使用DISTINCT子句删除可能的重复项:

INSERT into tab1( id, c1, c2, c3, c4 )

SELECT DISTINCT 2, c1, c2, c3, c4
FROM tab1 t1
WHERE id = 1
  AND NOT EXISTS (
    SELECT 'anything' FROM tab1 t2
    WHERE t1.c1=t2.c1
      AND t1.c2=t2.c2
      AND t1.c3=t2.c3
      AND t1.c4=t2.c4
      AND id = 2
)

答案 1 :(得分:0)

使用您的测试数据,我们可以执行以下交叉连接 - 这将为我们提供每个ID以及ID为1的所有行:

 select 
  T2.id
, T1.c1
, T1.c2
, T1.c3
, T1.c4
from (
  select *
  from tab1
  where id = 1 
) T1, ( select unique id from tab1 ) T2
;

-- result
ID  C1  C2  C3         C4  
1   a   b   01-FEB-18  c   
1   o   b   01-FEB-18  c   
1   a   b   04-MAY-18  c   
1   n   g   01-FEB-18  d   
2   a   b   01-FEB-18  c   
2   o   b   01-FEB-18  c   
2   a   b   04-MAY-18  c   
2   n   g   01-FEB-18  d 

然后,使用MINUS运算符并插入所有结果行。

insert into tab1 ( id, c1, c2, c3, c4 )
(
  select 
    T2.id
  , T1.c1
  , T1.c2
  , T1.c3
  , T1.c4
  from (
    select *
    from tab1
    where id = 1 
  ) T1, ( select unique id from tab1 ) T2
)
minus                -- do not insert existing rows
select * from tab1   
;

3 rows inserted.

Tab1现在包含:

select * from tab1 ;
ID  C1  C2  C3         C4  
1   a   b   01-FEB-18  c   
1   o   b   01-FEB-18  c   
1   a   b   04-MAY-18  c   
1   n   g   01-FEB-18  d   
2   a   b   01-FEB-18  c   
2   a   b   04-MAY-18  c   
2   n   g   01-FEB-18  d   
2   o   b   01-FEB-18  c

有关详细信息,请参阅dbfiddle

答案 2 :(得分:0)

最简单的解决方案是使用MERGE:

merge into tab1
using ( select 2 as id, c1, c2, c3, c4 
       from tab1
       where id = 1 -- optional
    ) q
on (q.id = tab1.id
    and q.c1 = tab1.c1
    and q.c2 = tab1.c2
    and q.c3 = tab1.c3
    and q.c4 = tab1.c4)
when not matched then
    insert values (q.id, q.c1, q.c2, q.c3, q.c4)
;

此解决方案将在tab1(id, c1, c2, c3, c4)定义一组唯一行的情况下工作。

这是a demo on SQL Fiddle

答案 3 :(得分:0)

只需创建一个临时表 TMP_TABLE 即可完整加入

CREATE TABLE TMP_TABLE AS SELECT *
FROM
(SELECT DISTINCT id FROM tab1 ) a,
(SELECT DISTINCT c1, c2, c3 FROM tab1 ) b