SQL (oracle) 使用另一个 table 中的值更新 table 中的一些记录
SQL (oracle) Update some records in table using values in another table
我要表 :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 1 10/01/2015
4 0 12/02/2015
5 null null
Table2
--------------------------------
ID VAL2 DATE1
--------------------------------
1 N 02/06/2015
1 N 01/08/2015
2 null null
3 O 05/04/2016
3 O 02/02/2015
4 O 01/07/2015
5 O 03/02/2015
5 N 10/01/2014
5 O 12/04/2015
我要更新:
- 列 VAL1(表 1)为“0”,如果 VAL2(表 2)等于 'O'
- 列 DATE1(表 1),每个 ID 最早的日期 2(表 2)(这里是我的问题)
(这两个表不是那么简单,只是为了说明,可以用ID列连接)。
这是我的代码:
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2) --To take the first DATE for each ID where VAL2='O' (not working fine)
FROM Table2 t2, Table1 t1
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Table2 = 'O')
AND VAL1<>'0'; --(for doing the update only if VAL1 not already equal to 0)
预期结果是:
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 10/01/2014
我得到的结果是:
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 10/01/2014
4 0 10/01/2014
5 0 10/01/2014
我的问题是无论 ID 是什么,DATE1 总是更新为同一日期。
您不应该在第一个子查询中第二次引用 table1
;这正在失去子查询和外部查询之间的相关性。如果您 运行 子查询本身,它总是会在 table2
中为 任何 ID 在 [=11= 中具有 val2='O'
的 ID 找到最低日期],即 10/01/2014。 (除非您的示例数据不一致;那实际上是 N
所以不会被考虑 - 您当前和预期的结果与您显示的数据不匹配,但您说它不是真实的)。符合更新条件的每一行 运行 都是相同的子查询并获得相同的值。
您需要维护外部查询和子查询之间的相关性,因此子查询应该使用外部 table1
进行连接,就像第二个子查询已经做的那样:
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2)
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Val2 = 'O')
AND VAL1<>'0';
您可以使用此 UPDATE 语句。
UPDATE TABLE1 T1
SET T1.VAL1 = '0',
T1.DATE1 = (SELECT MIN(T2.DATE2)
FROM TABLE2 T2
WHERE TRIM(T2.ID) = TRIM(T1.ID)
AND T2.VAL2='O')
WHERE T1.ID IN (SELECT T2.ID FROM TABLE2 T2 WHERE T2.VAL2='O')
希望对您有所帮助。
MYSQL解决方案
希望这个 MySql 语法也适用于 ORACLE。
SQL 的问题是它在计算最早日期时只考虑带有 VAL2=='O' 的记录。所以最后一条记录的日期如下面 table 所示。不考虑记录“5 N 10/01/2014”。
UPDATE Table1, (SELECT * FROM (SELECT * FROM table2 WHERE VAL2='O' ORDER BY ID, DATE1) X GROUP BY X.ID) T2
SET Table1.DATE1=T2.DATE1, Table1.VAL1=0
WHERE Table1.ID=T2.ID
..
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 **03/02/2015**
在 MySql 5.6.14
上测试
我要表 :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 1 10/01/2015
4 0 12/02/2015
5 null null
Table2
--------------------------------
ID VAL2 DATE1
--------------------------------
1 N 02/06/2015
1 N 01/08/2015
2 null null
3 O 05/04/2016
3 O 02/02/2015
4 O 01/07/2015
5 O 03/02/2015
5 N 10/01/2014
5 O 12/04/2015
我要更新:
- 列 VAL1(表 1)为“0”,如果 VAL2(表 2)等于 'O'
- 列 DATE1(表 1),每个 ID 最早的日期 2(表 2)(这里是我的问题)
(这两个表不是那么简单,只是为了说明,可以用ID列连接)。
这是我的代码:
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2) --To take the first DATE for each ID where VAL2='O' (not working fine)
FROM Table2 t2, Table1 t1
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Table2 = 'O')
AND VAL1<>'0'; --(for doing the update only if VAL1 not already equal to 0)
预期结果是:
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 10/01/2014
我得到的结果是:
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 10/01/2014
4 0 10/01/2014
5 0 10/01/2014
我的问题是无论 ID 是什么,DATE1 总是更新为同一日期。
您不应该在第一个子查询中第二次引用 table1
;这正在失去子查询和外部查询之间的相关性。如果您 运行 子查询本身,它总是会在 table2
中为 任何 ID 在 [=11= 中具有 val2='O'
的 ID 找到最低日期],即 10/01/2014。 (除非您的示例数据不一致;那实际上是 N
所以不会被考虑 - 您当前和预期的结果与您显示的数据不匹配,但您说它不是真实的)。符合更新条件的每一行 运行 都是相同的子查询并获得相同的值。
您需要维护外部查询和子查询之间的相关性,因此子查询应该使用外部 table1
进行连接,就像第二个子查询已经做的那样:
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2)
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Val2 = 'O')
AND VAL1<>'0';
您可以使用此 UPDATE 语句。
UPDATE TABLE1 T1
SET T1.VAL1 = '0',
T1.DATE1 = (SELECT MIN(T2.DATE2)
FROM TABLE2 T2
WHERE TRIM(T2.ID) = TRIM(T1.ID)
AND T2.VAL2='O')
WHERE T1.ID IN (SELECT T2.ID FROM TABLE2 T2 WHERE T2.VAL2='O')
希望对您有所帮助。
MYSQL解决方案
希望这个 MySql 语法也适用于 ORACLE。
SQL 的问题是它在计算最早日期时只考虑带有 VAL2=='O' 的记录。所以最后一条记录的日期如下面 table 所示。不考虑记录“5 N 10/01/2014”。
UPDATE Table1, (SELECT * FROM (SELECT * FROM table2 WHERE VAL2='O' ORDER BY ID, DATE1) X GROUP BY X.ID) T2
SET Table1.DATE1=T2.DATE1, Table1.VAL1=0
WHERE Table1.ID=T2.ID
..
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 **03/02/2015**
在 MySql 5.6.14
上测试