web-dev-qa-db-fra.com

Requête de mise à jour MySQL avec jointure gauche et regroupement par

J'essaie de créer une requête de mise à jour et je fais peu de progrès pour obtenir la bonne syntaxe. La requête suivante fonctionne:

SELECT t.Index1, t.Index2, COUNT( m.EventType ) 
    FROM Table t
    LEFT JOIN MEvents m ON
        (m.Index1 = t.Index1 AND
         m.Index2 = t.Index2 AND
        (m.EventType =  'A' OR m.EventType =  'B')
    ) 
    WHERE (t.SpecialEventCount IS NULL)
    GROUP BY t.Index1, t.Index2

Il crée une liste de triplets Index1, Index2, EventCounts. Il ne le fait que dans le cas où t.SpecialEventCount est NULL. La requête de mise à jour que j'essaie d'écrire doit définir ce SpecialEventCount sur ce nombre, c'est-à-dire COUNT (m.EventType) dans la requête ci-dessus. Ce nombre peut être 0 ou tout nombre positif (d'où la jointure gauche). Index1 et Index2 ensemble sont uniques dans le tableau t et ils sont utilisés pour identifier les événements dans MEvent.

Comment dois-je modifier la requête de sélection pour devenir une requête de mise à jour? C'est à dire. quelque chose comme

UPDATE Table SET SpecialEventCount=COUNT(m.EventType).....

mais je ne sais pas quoi mettre où et j'ai échoué avec de nombreuses suppositions différentes.

45
Rob

Je suppose que (Index1, Index2) est une clé unique sur Table, sinon j'attendrais la référence à t.SpecialEventCount pour entraîner une erreur.

Requête modifiée pour utiliser la sous-requête car cela ne fonctionnait pas avec GROUP BY

UPDATE
    Table AS t
    LEFT JOIN (
        SELECT
            Index1,
            Index2,
            COUNT(EventType) AS NumEvents
        FROM
            MEvents
        WHERE
            EventType = 'A' OR EventType = 'B'
        GROUP BY
            Index1,
            Index2
    ) AS m ON
        m.Index1 = t.Index1 AND
        m.Index2 = t.Index2
SET
    t.SpecialEventCount = m.NumEvents
WHERE
    t.SpecialEventCount IS NULL
81
Hammerite

Faire une jointure gauche avec une sous-requête va générer une table temporaire géante en mémoire qui n'aura pas d'index.

Pour les mises à jour, essayez d'éviter les jointures et d'utiliser plutôt des sous-requêtes corrélées:

UPDATE
    Table AS t
SET
    t.SpecialEventCount = (
        SELECT COUNT(m.EventType)
        FROM MEvents m
        WHERE m.EventType in ('A','B')
          AND m.Index1 = t.Index1
          AND m.Index2 = t.Index2
    )
WHERE
    t.SpecialEventCount IS NULL

Faites du profilage, mais cela peut être beaucoup plus rapide dans certains cas.

4
zvibo

mon exemple

update card_crowd  as cardCrowd
LEFT JOIN 
(
select cc.id , count(1) as num
from card_crowd cc LEFT JOIN 
card_crowd_r ccr on cc.id = ccr.crowd_id
group by cc.id
) as tt
on cardCrowd.id = tt.id
set cardCrowd.join_num = tt.num;
1
riverfan