2008-10-21 4 views
2

Сложность формулирования этого коррелированного подзапроса. У меня две таблицы фиктивных таблиц, foo и bar. foo имеет два поля foo_id и total_count. bar имеет два поля, секунды и идентификатор.MySQL коррелировал подзапрос

Мне нужно агрегировать секунды в строке для каждого отдельного идентификатора и обновить total_count в foo. id - это внешний ключ в баре для foo_id.

Я пытался что-то подобное без особой удачи:

UPDATE foo f1 set total_count = (SELECT SUM(seconds) from bar b1 INNER JOIN foo f2  WHERE b1.foo_id = f2.id) WHERE f1.foo_id = bar.id; 

ответ

1
UPDATE foo f1 
SET total_count = (SELECT SUM(seconds) 
FROM bar b1 WHERE b1.id = f1.foo_id) 

У вас должен быть доступ к соответствующему идентификатору foo в подзапросе, поэтому нет необходимости вступать в таблицу.

0

Я надеюсь, что я прямо понял ваш вопрос.

Вы следующие таблицы:

  • таблица foo - столбцы: id и total_count
  • стол bar - столбцы: foo_id (ссылки foo.id) и seconds

Следующий запрос должен работать (обновить все total_count строки в таблице foo):

UPDATE foo AS f1 
SET total_count = (
    SELECT SUM(seconds) 
    FROM bar INNER JOIN foo 
    WHERE foo_id = f1.id 
); 

Я не уверен, что вы пытаетесь сделать с вашим последним WHERE пунктом (WHERE f1.foo_id = bar.id;).

0

Это действительно открывает двери для непротиворечивости. Вы могли бы рассмотреть вопрос о создании вида, а не мутируют в Foo таблице:

CREATE VIEW foo AS 
SELECT id, sum(seconds) from bar group by id; 
0

Просто, чтобы предложить альтернативу, я хотел бы использовать изящные обновления нескольких таблиц MySQL оснащены:

UPDATE foo SET total_count = 0; 

UPDATE foo JOIN bar ON (foo.foo_id = bar.id) 
    SET foo.total_count = foo.total_count + bar.seconds; 
1

В больших наборах данных, коррелированные подзапросы могут быть очень ресурсоемкими. Присоединение к производной таблице, содержащей соответствующие агрегаты, может быть намного более эффективным:

create table foo (foo_id int identity, total_count int default 0) 
create table bar (foo_id int, seconds int) 

insert into foo default values 
insert into foo default values 
insert into foo default values 

insert into bar values (1, 10) 
insert into bar values (1, 11) 
insert into bar values (1, 12) 
    /* total for foo_id 1 = 33 */ 
insert into bar values (2, 10) 
insert into bar values (2, 11) 
    /* total for foo_id 2 = 21 */ 
insert into bar values (3, 10) 
insert into bar values (3, 19) 
    /* total for foo_id 3 = 29 */ 

select * 
from foo 

foo_id  total_count 
----------- ----------- 
1   0 
2   0 
3   0 

update f 
set  total_count = sumsec 
from foo f 
     inner join (
        select foo_id 
          , sum(seconds) sumsec 
        from bar 
        group by foo_id 
        ) a 
      on f.foo_id = a.foo_id 

select * 
from foo 

foo_id  total_count 
----------- ----------- 
1   33 
2   21 
3   29 
Смежные вопросы