MySQL correlacionada subconsulta
-
03-07-2019 - |
Pergunta
Tendo dificuldade em articular essa subconsulta correlacionada. Eu tenho duas tabelas tabelas fictícios, foo e bar. foo tem dois campos de foo_id e TOTAL_COUNT. bar possui dois campos, segundos e id.
Eu preciso agregar os segundos no bar para cada id individual e atualizar o TOTAL_COUNT em foo. id é uma chave estrangeira no bar para foo_id.
Eu tentei algo semelhante sem muita sorte:
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;
Solução
UPDATE foo f1
SET total_count = (SELECT SUM(seconds)
FROM bar b1 WHERE b1.id = f1.foo_id)
Você deve ter acesso ao ID foo apropriado dentro do sub-consulta, por isso não há necessidade de juntar-se na tabela.
Outras dicas
Em grandes conjuntos de dados, subconsultas correlacionados podem ser muito utilização intensiva de recursos. Juntando-se a uma tabela derivada contendo os agregados apropriados podem ser muito mais eficiente:
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
Isso realmente abre a porta para problemas de consistência. Você pode considerar a criação de uma exibição em vez de mutação tabela de foo:
CREATE VIEW foo AS
SELECT id, sum(seconds) from bar group by id;
Apenas para oferecer uma alternativa, eu gosto de usar atualizações multi-mesa bacana do MySQL possuem:
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;
Espero que eu entendi sua pergunta direita.
Você tem as seguintes tabelas:
- tabela
foo
- colunas:id
etotal_count
- tabela
bar
- colunas:foo_id
(referênciasfoo.id
) eseconds
A consulta seguinte deve funcionar (atualizar todas as linhas total_count
em foo
tabela):
UPDATE foo AS f1
SET total_count = (
SELECT SUM(seconds)
FROM bar INNER JOIN foo
WHERE foo_id = f1.id
);
Eu não sei o que você está tentando fazer com sua cláusula WHERE
passado (WHERE f1.foo_id = bar.id;
).