首先,我使用 MonetDB Database Server Toolkit v1.1 (Feb2013-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;
当它们的 id 匹配时,我们需要将 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 中,如何在更新语句中正确编写这样的子查询?
看起来 MonetDB 在 select 中支持 with 子句,但在 update 中不支持。
with tmp as (select t2.id, sum(t2.data) as data from t2 group by t2.id) select * from tmp;
我也很想知道使用子查询和创建临时表之间的性能差异。
谢谢!