首先,我使用的是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;
我也很想知道使用子查询和创建临时表之间的性能差异。
谢谢!
答案 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);