如何使用子查询中的另一个表或聚合结果更新表?

时间:2014-03-01 00:11:13

标签: sql-update subquery aggregate-functions monetdb

首先,我使用的是MonetDB数据库服务器工具包v1.1(2013年2月-SP1)中的MonetDB分支

我有两个表,想要在不创建临时表的情况下完成以下两个函数:

1)从另一个表更新一个表;和 2)从另一个表的聚合更新一个表。

我想出了如何在MySQL和Postgresql中执行它们,但类似的查询在MonetDB中失败了。

对于1),假设我有以下两个表:

drop table t1; create table t1(id int, data int);
drop table t2; create table t2(id int, data int);
delete from t1; insert into t1 values (0, 0), (1,1), (2,2); select*from t1;
delete from t2; insert into t2 values (1,2), (2, 3), (3,4); select*from t2;

当ids匹配时,我们需要将t1.data设置为t1.data + t2.data,t1.id = t2.id。

在MySQL中,我们可以使用:

update t1 inner join t2 on t1.id=t2.id set t1.data=t1.data+t2.data;

在Postgresql中,我们可以使用:

with tmp as (select t1.id, t1.data+t2.data as data from t1,t2 where t1.id=t2.id) update t1 set data = tmp.data from tmp where t1.id=tmp.id;select*from t1;

或两者兼而有之,我们可以使用:

update t1 set data=(select t1.data+t2.data from t2 where t2.id=t1.id) where exists (select * from t2 where t1.id=t2.id);

但是它们都不能在MonetDB中运行。

此问题类似于之前提出的问题(https://www.monetdb.org/pipermail/users-list/2011-August/005072.html),但建议的答案看起来不正确。这两个表对于元组id = 2具有相同的值。

update t1 set data=(select data+t2.data from t2 where t2.id=t1.id) where exists (select * from t2 where t1.id=t2.id);

因此在这个查询中,select的第一个子查询中的数据字段实际上来自t2而不是t1。但是,如果我们更改为t1.data,则解析器将无法识别名称t1。它以某种方式连线,它可以识别条件子句中的t1.id.

以下查询不正确:

update t1 set data=(select t1.data + t2.data from t1, t2 where t2.id = t1.id) where exists (select t2.id from t2 where t2.id = t1.id);

由于子查询独立于外部查询,可能会导致多个值违反赋值基数。

同时更改t1和t2中的字段名称也没有用。

对于2),假设我们有以下两个表:

delete from t1; insert into t1 values (0, 0), (1,1), (2,2); select * from t1;
delete from t2; insert into t2 values (1,2), (2, 3), (3,4), (2,5); select * from t2;

我们希望聚合t2中的值并将结果分配给t1。

在MySQL中,我们可以使用:

update t1 inner join t2 on t1.id=t2.id set t1.data=(select sum(t2.data) from t2 where t2.id=t1.id group by t2.id);

或者在Postgresql中,我们可以使用:

with tmp as (select t2.id, sum(t2.data) as data from t2 group by t2.id) update t1 set data=tmp.data from tmp where t1.id=tmp.id;

在MonetDB中,如何在update语句中正确编写这样的子查询?

看起来MonetDB支持select中的with子句,但不支持更新。

with tmp as (select t2.id, sum(t2.data) as data from t2 group by t2.id) select * from tmp; 

我也很想知道使用子查询和创建临时表之间的性能差异。

谢谢!

1 个答案:

答案 0 :(得分:1)

根据MonetDB邮件列表Niels的回复,随着2014年1月发布,这两个功能可以用以下两种工作形式表示:

1):

update t1 set data=(select t1.data+t2.data from t2 where t2.id=t1.id) where exists (select * from t2 where t1.id=t2.id);

2):

update t1 set data = (select sum(t2.data) from t2 where t2.id=t1.id group by t2.id) where exists (select * from t2 where t1.id=t2.id);