Как обновить таблицу, используя другую таблицу или результаты агрегации из подзапроса?

Во-первых, я использую ветку MonetDB из MonetDB Database Server Toolkit v1.1 (Feb2013-SP1).

У меня есть две таблицы, и я хочу выполнить следующие две функции без создания временной таблицы:

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;

Нам нужно установить 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);

Таким образом, в этом запросе поле данных в 1-м подзапросе 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 поддерживает предложение with в select, но не в update.

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

Мне также интересно узнать разницу в производительности между использованием подзапросов и созданием временных таблиц.

Спасибо!


person Ning    schedule 01.03.2014    source источник


Ответы (1)


Согласно ответу из списка рассылки Niels из MonetDB, с выпуском в январе 2014 года две функции могут быть выражены в следующих двух рабочих формах:

Для 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);
person Ning    schedule 04.03.2014
comment
Я попробовал эти решения, но столкнулся с другой проблемой. В моем случае таблицы находятся в разных схемах, поэтому я попробовал schema1.table.id = schema2.table.id, а взамен получил TODO: column names of level >= 3 :) - person marcin_koss; 27.10.2015