Вопрос

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

Мне нужно агрегировать секунды в баре для каждого отдельного идентификатора и обновить total_count в foo.id — это внешний ключ в bar для 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;
Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

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

  • стол 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;).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top