Sous-requête corrélée MySQL
-
03-07-2019 - |
Question
Vous rencontrez des difficultés pour articuler cette sous-requête corrélée. J'ai deux tables tables fictives, foo et bar. Foo a deux champs de foo_id et total_count. la barre a deux champs, secondes et id.
J'ai besoin d'agréger les secondes en bars pour chaque identifiant individuel et de mettre à jour le total_count dans foo. id est une clé étrangère en barre pour foo_id.
J'ai essayé quelque chose de similaire sans trop de chance:
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;
La solution
UPDATE foo f1
SET total_count = (SELECT SUM(seconds)
FROM bar b1 WHERE b1.id = f1.foo_id)
Vous devriez avoir accès à l'ID de foo approprié dans la sous-requête, il n'est donc pas nécessaire de rejoindre la table.
Autres conseils
Dans les grands ensembles de données, les sous-requêtes corrélées peuvent nécessiter beaucoup de ressources. La jonction à une table dérivée contenant les agrégats appropriés peut être beaucoup plus efficace:
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
Cela ouvre vraiment la porte aux problèmes de cohérence. Vous pouvez envisager de créer une vue plutôt que de transformer la table foo:
CREATE VIEW foo AS
SELECT id, sum(seconds) from bar group by id;
Juste pour offrir une alternative, j'aime utiliser la fonctionnalité astucieuse de mises à jour multi-tables 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;
J'espère avoir bien compris votre question.
Vous avez les tables suivantes:
- table
toto
- colonnes:id
ettotal_count
- table
barre
- colonnes:foo_id
(référencesfoo.id
) etsecondes
La requête suivante doit fonctionner (mettez à jour toutes les lignes total_count
de la table toto
):
UPDATE foo AS f1
SET total_count = (
SELECT SUM(seconds)
FROM bar INNER JOIN foo
WHERE foo_id = f1.id
);
Je ne sais pas trop ce que vous essayez de faire avec votre dernière clause WHERE
( WHERE f1.foo_id = bar.id;
).