MySQL коррелированный подзапрос - PullRequest
2 голосов
/ 21 октября 2008

Трудно сформулировать этот коррелированный подзапрос. У меня есть две таблицы фиктивных таблиц, Foo и Bar. У foo есть два поля: foo_id и total_count. Бар имеет два поля, секунды и идентификатор.

Мне нужно агрегировать секунды в баре для каждого отдельного идентификатора и обновлять 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;

Ответы [ 5 ]

1 голос
/ 07 ноября 2008

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

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
1 голос
/ 21 октября 2008
UPDATE foo f1
SET total_count = (SELECT SUM(seconds)
FROM bar b1 WHERE b1.id = f1.foo_id)

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

0 голосов
/ 22 октября 2008

Просто для того, чтобы предложить альтернативу, мне нравится использовать отличную функцию обновления 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;
0 голосов
/ 21 октября 2008

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

CREATE VIEW foo AS
SELECT id, sum(seconds) from bar group by id;
0 голосов
/ 21 октября 2008

Надеюсь, я правильно понял ваш вопрос.

У вас есть следующие таблицы:

  • таблица 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;).

...