Коррелированный подзапрос MySQL
-
03-07-2019 - |
Вопрос
Возникли трудности с формулированием этого коррелированного подзапроса.У меня есть две фиктивные таблицы: 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;
).