Funzione aggregata in una query di aggiornamento SQL?


98

Sto cercando di impostare il valore in una tabella sulla somma dei valori in un'altra tabella. Qualcosa in questo senso:

UPDATE table1
SET field1 = SUM(table2.field2)
FROM table1
INNER JOIN table2 ON table1.field3 = table2.field3
GROUP BY table1.field3

Ovviamente, così com'è, non funzionerà - SETnon supporta SUMe non supporta GROUP BY.

Dovrei saperlo, ma la mia mente sta disegnando un vuoto. Che cosa sto facendo di sbagliato?


Ottima domanda ... vorrei poter votare più di una volta.
Joe

Risposte:


149
UPDATE t1
SET t1.field1 = t2.field2Sum
FROM table1 t1
INNER JOIN (select field3, sum(field2) as field2Sum
   from table2
  group by field3) as t2
on t2.field3 = t1.field3  

41
Ho messo le tre query fianco a fianco e ho eseguito un piano di esecuzione. Questa risposta ha avuto un costo del 5%.
Margaret

Elegante, facile da implementare ... Dove sei stato tutto il giorno ??? Ci sto sbattendo la testa per più di un'ora ormai :)
Ange1

1
Importante: fai attenzione se uno dei campi in base a cui stai raggruppando potrebbe essere nullable (ad esempio field3 sopra). avresti bisogno di modificare il 'join' per tenere conto di questo o le vostre somme saranno imprecisi ( stackoverflow.com/a/14366034/16940 )
Simon_Weaver

10

Uso:

UPDATE table1
   SET field1 = (SELECT SUM(t2.field2) 
                   FROM TABLE2 t2 
                  WHERE t2.field3 = field2)

14
Ho messo le tre query fianco a fianco e ho eseguito un piano di esecuzione. Questa risposta ha avuto un costo del 44%.
Margaret

questo non ha funzionato per me, perché t2.filed3 aveva lo stesso nome di table1.field2, quindi il join eseguito dietro le quinte non funzionava correttamente. (Suppongo che ci sia un collegamento dietro le quinte)
Joe

5

Oppure potresti usare un mix di risposte JBrooks e OMG Ponies :

UPDATE table1
   SET field1 = (SELECT SUM(field2)
                   FROM table2 AS t2
                  WHERE t2.field3 = t1.field3)
  FROM table1 AS t1

16
Ho messo le tre query fianco a fianco e ho eseguito un piano di esecuzione. Questa risposta ha avuto un costo del 51%.
Margaret

D'accordo! E grazie per il feedback. Lo aggiungerò alla mia cassetta degli attrezzi. :-)
Paulo Santos

Questo perché stai utilizzando una SUBQUERY che deve attivare SUM () ogni riga valida, anche con l'ottimizzatore
clifton_h

4

Una buona situazione per utilizzare CROSS APPLY

UPDATE t1
   SET t1.field1 = t2.field2Sum
  FROM table1 t1
 CROSS APPLY (SELECT SUM(field2) as field2Sum
                FROM table2 t2
               WHERE t2.field3 = t1.field3) AS t2

3

So che la domanda è contrassegnata con SQL Server, ma fai attenzione con UPDATE con JOIN se stai usando PostgreSQL . La risposta di @JBrooks non funzionerà:

UPDATE t1
SET t1.field1 = t2.field2Sum
FROM table1 t1
INNER JOIN (...) as t2
on t2.field3 = t1.field3  

Dovrai adattarlo a:

UPDATE table1 t1
SET t1.field1 = t2.field2Sum
FROM (...) as t2
WHERE t2.field3 = t1.field3  

Vedere il parametro from_listnel documento per capire perché FROMè considerato da PostgreSQL come un auto-join: https://www.postgresql.org/docs/9.5/static/sql-update.html#AEN89239


0

Puoi anche usare CTE come di seguito.

;WITH t2 AS (
    SELECT field3, SUM(field2) AS field2
    FROM table2
    GROUP BY field3
)
UPDATE table1
SET table1.field1 = t2.field2
FROM table1
INNER JOIN t2 ON table1.field3 = t2.field3
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.