我在ORACLE SQL操作上遇到了麻烦。 首先,我有两张桌子,
TEST_TABLE_A
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD1', 100, 200, 'ACTIVE');
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD2', 300, 400, 'ACTIVE');
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD3', 500, 600, 'ACTIVE');
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD4', 700, 800, 'ACTIVE');
TEST_TABLE_B
Insert into TEST_TABLE_B (NAME, VAL1, VAL2) Values ('HEAD1', 1, 2);
Insert into TEST_TABLE_B (NAME, VAL1, VAL2) Values ('HEAD4', 700, 800);
Insert into TEST_TABLE_B (NAME, VAL1, VAL2) Values ('HEAD5', 900, 1000);
我的作业如下, 1.将表b中的数据同步到表a 2.当找到具有相同值的相同名称时,则忽略 3.当使用不同的值找到相同的名称时,将数据插入到表A中,并使用相同的名称从B中获取值,并使用' INACTIVE'更新旧行。状态 4.如果表A中没有基于表B的数据,则将数据插入表A
我的查询是这样的,
MERGE INTO TEST_TABLE_A TGT
USING TEST_TABLE_B SRC
ON (TGT.NAME = SRC.NAME)
WHEN MATCHED THEN
UPDATE SET TGT.VAL1 = SRC.VAL1,
TGT.VAL2 = SRC.VAL2
WHEN NOT MATCHED THEN
INSERT (TGT.NAME, TGT.VAL1, TGT.VAL2, TGT.STATUS)
VALUES (SRC.NAME, SRC.VAL1, SRC.VAL2, 'ACTIVE');
所以我面临的问题是我不能让#3工作。我尝试了很多SQL的组合,它只是没有碰巧工作。
如何通过忽略两个表中具有相同值的相同名称来使数字2工作?
我希望结果会像这样
TEST_TABLE_A
NAME VAL1 VAL2 STATUS
-----------------------------
HEAD1 100 200 INACTIVE
HEAD1 1 2 ACTIVE
HEAD2 300 400 INACTIVE
HEAD3 500 600 INACTIVE
HEAD4 700 800 ACTIVE
HEAD5 900 1000 ACTIVE
我真的很感谢你们的帮助。 问候
答案 0 :(得分:0)
试试这个:
如果HEAD2和HEAD3是非活动的
--> Update the data that does not exist in table BLE_B to be INACTIVE
Update BLE_A
Set STATUS = 'INACTIVE'
From BLE_A a
Left Join BLE_B b
On b.Name = a.Name
And b.Val1 = a.Val1
And b.Val2 = a.Val2
Where b.Name is Null
--> Insert the data from BLE_B that does not exist in table BLE_A
--> or insert the data that different values with table BLE_A
Insert Into BLE_A
Select b.*, 'ACTIVE'
From BLE_B b
Left Join BLE_A a
On a.Name = b.Name
And a.Val1 = b.Val1
And a.Val2 = b.Val2
Where b.Name is Null
答案 1 :(得分:0)
您不能只为#3使用一个合并,因为您需要在相同的ON条件下更新和插入。
update test_table_a a set a.status = 'INACTIVE'
where exists (select 1 from test_table_b b
where b.name = a.name and (b.val1 != a.val1 or b.val2 != a.val2));
merge into test_table_a a using test_table_b b on (b.val1 = a.val1 and b.val2 = a.val2)
when not matched then insert values (b.name, b.val1, b.val2, 'ACTIVE');
但我不明白为什么在你的输出中HEAD2和HEAD3处于' INACTIVE'状态。也许你还需要标记为“不活跃”。 TEST_TABLE_A中的行不存在于TEST_TABLE_B中(在这种情况下,您可以通过添加此条件来更改第一个更新:"或者不存在(从test_table_b b中选择1,其中b.name = a.name) &#34)
答案 2 :(得分:0)
我希望结果会像这样
TEST_TABLE_A
NAME VAL1 VAL2 STATUS
-----------------------------
HEAD1 100 200 INACTIVE
HEAD1 1 2 ACTIVE
HEAD2 300 400 INACTIVE
HEAD3 500 600 INACTIVE
HEAD4 700 800 ACTIVE
HEAD5 900 1000 ACTIVE
好的,让我们看看如何才能满足SQL的每个规则。
1.首先,这两个表只是一个简单的UNION
。
2.然后,需要删除NAME
,VAL1
和VAL2
列上重复的行。因此,请使用ROW_NUMBER
analytic。
3.最后,选择RANK
为1的行。
SQL> SELECT name,
2 val1,
3 val2,
4 status
5 FROM
6 (SELECT a.*,
7 row_number() over(partition BY a.val1, a.val2 order by a.name, a.val1, a.val2) rn
8 FROM
9 ( SELECT name, val1, val2,'INACTIVE' status FROM TEST_TABLE_A
10 UNION
11 SELECT b.*, 'ACTIVE' status FROM TEST_TABLE_B b ORDER BY 1
12 ) A
13 )
14 WHERE rn = 1
15 /
NAME VAL1 VAL2 STATUS
-------------------- ---------- ---------- --------
HEAD1 1 2 ACTIVE
HEAD1 100 200 INACTIVE
HEAD2 300 400 INACTIVE
HEAD3 500 600 INACTIVE
HEAD4 700 800 ACTIVE
HEAD5 900 1000 ACTIVE
6 rows selected.
SQL>
因此,它可以提供您想要的输出。
*更新**在OP的请求中添加测试用例
SQL> SELECT * FROM test_table_a;
NAME VAL1 VAL2 STATUS
-------------------- ---------- ---------- --------------------
HEAD1 100 200 ACTIVE
HEAD2 300 400 ACTIVE
HEAD3 500 600 ACTIVE
HEAD4 700 800 ACTIVE
SQL>
SQL> CREATE TABLE test_table_a_new AS
2 SELECT name,
3 val1,
4 val2,
5 status
6 FROM
7 (SELECT a.*,
8 row_number() over(partition BY a.val1, a.val2 order by a.name, a.val1, a.val2) rn
9 FROM
10 ( SELECT name, val1, val2,'INACTIVE' status FROM TEST_TABLE_A
11 UNION
12 SELECT b.*, 'ACTIVE' status FROM TEST_TABLE_B b ORDER BY 1
13 ) A
14 )
15 WHERE rn = 1
16 /
Table created.
SQL>
SQL> DROP TABLE test_table_a PURGE
2 /
Table dropped.
SQL>
SQL> alter table test_table_a_new rename to test_table_a
2 /
Table altered.
SQL> select * from test_table_a
2 /
NAME VAL1 VAL2 STATUS
-------------------- ---------- ---------- --------
HEAD1 1 2 ACTIVE
HEAD1 100 200 INACTIVE
HEAD2 300 400 INACTIVE
HEAD3 500 600 INACTIVE
HEAD4 700 800 ACTIVE
HEAD5 900 1000 ACTIVE
6 rows selected.
SQL>