MySQL / SQL: Mise à jour avec sous-requête corrélée à partir de la table mise à jour elle-même
-
22-07-2019 - |
Question
J'ai une question générique que je vais essayer d'expliquer à l'aide d'un exemple.
Dites que j'ai un tableau avec les champs: "id", "nom", "catégorie", "apparences". et "rapport"
L’idée est que j’ai plusieurs éléments, chacun lié à une seule catégorie et que "" apparaît" " plusieurs fois. Le champ de rapport doit inclure le pourcentage d'apparences de chaque élément par rapport au nombre total d'apparences d'éléments dans la catégorie.
En pseudo-code, il me faut ce qui suit:
-
Pour chaque catégorie
trouver la somme totale des apparences pour les articles qui lui sont liés. Par exemple, cela peut être fait avec (sélectionner la somme ("apparences") du groupe de tables par catégorie
) -
Pour chaque élément
définissez la valeur du rapport en divisant les apparences de l'élément par la somme trouvée pour la catégorie ci-dessus
Maintenant, j'essaie de réaliser cela avec une seule requête de mise à jour, mais je n'arrive pas à le faire. Ce que je pensais devoir faire, c'est:
update Table T
set T.ratio = T.appearances /
(
select sum(S.appearances)
from Table S
where S.id = T.id
)
Mais MySQL n’accepte pas l’alias T dans la colonne update et je n’ai trouvé aucun autre moyen d’y parvenir.
Des idées?
La solution
Après les deux réponses que j'ai reçues (aucune n'étant complète, j'ai donc écrit la mienne), ce que j'ai finalement fait est la suivante:
UPDATE Table AS target
INNER JOIN
(
select category, appearances_sum
from Table T inner join (
select category as cat, sum(appearances) as appearances_sum
from Table
group by cat
) as agg
where T.category = agg.cat
group by category
) as source
ON target.category = source.category
SET target.probability = target.appearances / source.appearances_sum
Cela fonctionne très rapidement. J'ai également essayé avec une sous-requête corrélée mais elle était beaucoup plus lente (ordres de grandeur), donc je m'en tiens à la jointure.
Autres conseils
Utilisez les jointures juste après UPDATE: Manuel de référence & # 8211; 13.2.11 Syntaxe UPDATE
alors UPDATE table1 interne rejoindre table2 sur .... set table1.foo = valeur où table2.bla = une autre valeur
Avec ce genre de choses, regardez toujours le manuel. MySql a un manuel de référence approprié, il ne devrait donc pas être aussi difficile d’obtenir la bonne syntaxe;)
Voici comment cela se fait dans mssql, je pense que mysql est identique ou similaire:
create table T (id int, ratio float, appearances int)
insert T values (1, null, 2)
insert T values (1, null, 3)
update T
set ratio = cast(appearances as float)/ agg.appearancesSum
from T join (
select id, sum(appearances) as appearancesSum
from T
group by id
) as agg on t.id = agg.id