Subconsulta correlacionada de MySQL
-
03-07-2019 - |
Pregunta
Dificultad para articular esta subconsulta correlacionada. Tengo dos mesas ficticias de tablas, foo y bar. foo tiene dos campos de foo_id y total_count. La barra tiene dos campos, segundos e id.
Necesito agregar los segundos en la barra para cada ID individual y actualizar el total_count en foo. ID es una clave externa en la barra para foo_id.
He intentado algo similar sin mucha suerte:
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;
Solución
UPDATE foo f1
SET total_count = (SELECT SUM(seconds)
FROM bar b1 WHERE b1.id = f1.foo_id)
Debes tener acceso a la ID de foo apropiada dentro de la subconsulta, por lo que no es necesario que te unas a la tabla.
Otros consejos
En conjuntos de datos más grandes, las subconsultas correlacionadas pueden ser muy intensivas en recursos. Unirse a una tabla derivada que contiene los agregados apropiados puede ser mucho más 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
Esto realmente abre la puerta a problemas de consistencia. Podría considerar crear una vista en lugar de mutar la tabla foo:
CREATE VIEW foo AS
SELECT id, sum(seconds) from bar group by id;
Solo para ofrecer una alternativa, me gusta usar la ingeniosa función de actualizaciones de múltiples tablas de 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;
Espero haber entendido bien tu pregunta.
Tienes las siguientes tablas:
- tabla
foo
- columnas:id
ytotal_count
- tabla
barra
- columnas:foo_id
(hace referencia afoo.id
) yseconds
La siguiente consulta debería funcionar (actualizar todas las filas total_count
en la tabla foo
):
UPDATE foo AS f1
SET total_count = (
SELECT SUM(seconds)
FROM bar INNER JOIN foo
WHERE foo_id = f1.id
);
No estoy seguro de qué intentas hacer con tu última cláusula WHERE
( WHERE f1.foo_id = bar.id;
).