Funkcja agregująca w zapytaniu aktualizującym SQL?

98

Próbuję ustawić wartość w jednej tabeli na sumę wartości w innej tabeli. Coś w tym stylu:

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

Oczywiście w obecnym stanie to nie zadziała - SETnie obsługuje SUMi nie obsługuje GROUP BY.

Powinienem to wiedzieć, ale w moim umyśle pojawia się pustka. Co ja robię źle?

Małgorzata
źródło
Świetne pytanie ... Chciałbym móc zagłosować za więcej niż raz.
Joe

Odpowiedzi:

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  
JBrooks
źródło
41
Położyłem trzy zapytania obok siebie i wykonałem plan wykonania. Ta odpowiedź kosztowała 5%.
Margaret
Elegancki, łatwy do wykonania ... Gdzie byłeś cały dzień ???
Wbijam
1
Ważne: Uważaj, jeśli którekolwiek z pól, według których grupujesz, może mieć wartość null (np. Field3 powyżej). musisz zmodyfikować
opcję
10

Posługiwać się:

UPDATE table1
   SET field1 = (SELECT SUM(t2.field2) 
                   FROM TABLE2 t2 
                  WHERE t2.field3 = field2)
Kucyki OMG
źródło
14
Położyłem trzy zapytania obok siebie i wykonałem plan wykonania. Ta odpowiedź kosztowała 44%.
Margaret
to nie zadziałało dla mnie, ponieważ t2.filed3 miał taką samą nazwę jak table1.field2, więc sprzężenie wykonane za kulisami nie działało poprawnie. (Zakładam, że za kulisami jest połączenie)
Joe
5

Możesz też użyć kombinacji odpowiedzi JBrooks i OMG Kucy :

UPDATE table1
   SET field1 = (SELECT SUM(field2)
                   FROM table2 AS t2
                  WHERE t2.field3 = t1.field3)
  FROM table1 AS t1
Paulo Santos
źródło
16
Położyłem trzy zapytania obok siebie i wykonałem plan wykonania. Ta odpowiedź kosztowała 51%.
Margaret
Okej! Dziękuję za informację zwrotną. Dodam to do mojego zestawu narzędzi. :-)
Paulo Santos
Dzieje się tak, ponieważ używasz SUBQUERY, które musi odpalać SUMA () w każdym prawidłowym wierszu, nawet z optymalizatorem
clifton_h
4

Dobra sytuacja do użycia 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
Jonathan Roberts
źródło
3

Wiem, że pytanie jest oznaczone jako SQL Server, ale zachowaj ostrożność podczas UPDATE z JOIN, jeśli używasz PostgreSQL . Odpowiedź @JBrooks nie zadziała:

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

Będziesz musiał go dostosować do:

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

Zobacz parametr from_listw dokumencie, aby dowiedzieć się, dlaczego FROMjest uważany przez PostgreSQL za łączenie własne: https://www.postgresql.org/docs/9.5/static/sql-update.html#AEN89239

Bludwarf
źródło
0

Możesz także użyć CTE jak poniżej.

;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
Karan
źródło