Zahlen addieren von bestimmten Feldern

ramboni

Benutzer
Beiträge
17
Hallo zusammen,

ich bräuchte mal eure Hilfe.


Ich habe eine Mastertabelle (A)
Count Name
200 Tom
150 Nina
100 Thomas


"Zubringer-Tabelle" (B)
Count Name
35 Thorsten
30 Tom
20 Nina
5 Thomas



Ich möchte nun aus der Zubringer (B) den Count vom Namen in die Master (A) schreiben (addieren) wenn vorhanden
bzw. neu schreiben wenn noch nicht vorhanden.

So dass nach Ausführung des Statements folgendes entsteht:

Count Name
230 Tom
170 Nina
105 Thomas
35 Thorsten


Geht sowas mit SQL in einem Statement?
Wenn ja, wie ? :)


Gruß und Danke :)
 
Werbung:
geht:

Code:
postgres=# select * from mastertabelle ;
 count |  name  
-------+--------
   200 | tom
   150 | nina
   100 | thomas
(3 rows)

postgres=# select * from zubringertabelle ;
 count |   name   
-------+----------
    35 | thorsten
    30 | tom
    20 | nina
     5 | thomas
(4 rows)

postgres=# with foo as (select * from mastertabelle union all select * from zubringertabelle ) select name, sum(count) from foo group by name;
   name   | sum 
----------+-----
 tom      | 230
 thomas   | 105
 thorsten |  35
 nina     | 170
(4 rows)

postgres=#

Dein Tabellendesign ist für die Tonne, Du hast 2 identisch aufgebaute Tabellen.
 
Ahhhh, hatte es falsch verstanden. Nun denn:

Code:
postgres=# select * from mastertabelle ;
 count |  name  
-------+--------
   200 | tom
   150 | nina
   100 | thomas
(3 rows)

postgres=# select * from zubringertabelle ;
 count |   name   
-------+----------
    35 | thorsten
    30 | tom
    20 | nina
     5 | thomas
(4 rows)

postgres=# begin;
BEGIN
postgres=*# insert into mastertabelle select * from zubringertabelle on conflict (name) do update set count = mastertabelle.count + excluded.count;
INSERT 0 4
postgres=*# select * from mastertabelle ;
 count |   name   
-------+----------
    35 | thorsten
   230 | tom
   170 | nina
   105 | thomas
(4 rows)

postgres=*#

Nun ist es in mastertabelle dazuaddiert.

Noch cooler als ON CONFLICT (ich habe dazu noch einen PK auf die Spalte namen gesetzt) ist MERGE:

Code:
postgres=!# rollback;
ROLLBACK
postgres=# begin;
BEGIN
postgres=*# merge into mastertabelle m using zubringertabelle z on (m.name=z.name) when matched then update set count = m.count + z.count when not matched then insert (count, name) values (z.count, z.name);
MERGE 4
postgres=*# select * from mastertabelle ;
 count |   name   
-------+----------
    35 | thorsten
   230 | tom
   170 | nina
   105 | thomas
(4 rows)

postgres=*#

Und jetzt das ABER:
* ich verwende PostgreSQL
* MERGE gibt es erst ab Version 15 (die noch nicht released ist, ich verwende Beta)
* Ob MySQL wenigstens eine der Features wie oben hat, weiß ich nicht
 
@ramboni Ich kann nur empfehlen, nicht die Summe (der Mastertabelle und der Zubringertabelle) in die Mastertabelle zu schreiben. Besser wäre dass Du ein zusätzliches Attribut mit dem Wert der Zubringertabelle einfügst. Zusätzliche Anmerkung count ist in aller Regel ein reserviertes Keywort und sollte nicht als Attributname verwendet werden.

statement könnte dann so aussehen
select name, sum(cnt_mt), sum(cnt_zb) from (
select name, cnt_mt, 0 cnt_zb from mastertabelle
union all
select name, 0, cnt from Zubringertabelle
) q1 group by name
 
Ich kann nur empfehlen, nicht die Summe (der Mastertabelle und der Zubringertabelle) in die Mastertabelle zu schreiben.
vermutlich handelt es sich hier um z.B. einen Import von Artikeln in ein Lager. Da ist schon was drin (mastertabelle) und es werden Dinge hinzugefügt (zubringertabelle). Dabei kann es sich auch um neue Artikel handeln, und das passiert vermutlich mit einer gewissen Regelmäßigkeit.
 
Für dem Import kann man die beiden Teilsummen immer noch zusammenrechnen, aber ohne dies zusätzliche Zeile kann man nicht mehr feststellen, ob die Merge Operation zwischen den beiden Tabellen schon durchgeführt wurde. Deshalb kann man von solchen Konstrukten nur abraten.
Meine Antworten basieren übrigens ausschließend auf die Informationen, die genannt wurden und nur auf zusätzlich Vermutungen, wenn ich es explizit dazu schreibe.
 
Werbung:
aber ohne dies zusätzliche Zeile kann man nicht mehr feststellen, ob die Merge Operation zwischen den beiden Tabellen schon durchgeführt wurde. Deshalb kann man von solchen Konstrukten nur abraten.
Nun ja, der Fragesteller WOLLTE das in seiner Mastertabelle aufaddiert haben. Punkt. Und man KANN in einem Statement, also atomar in einer Transaktion, auch gleich die 'Zubringertabelle' löschen, um ganz sicher zu gehen:

Code:
postgres=# select * from mastertabelle ;
 count |   name   
-------+----------
    35 | thorsten
   230 | tom
   170 | nina
   105 | thomas
(4 rows)

postgres=# select * from zubringertabelle ;
 count |   name   
-------+----------
    35 | thorsten
    30 | tom
    20 | nina
     5 | thomas
(4 rows)

postgres=# with z_tmp as (delete from zubringertabelle returning *) merge into mastertabelle m using z_tmp z on (m.name=z.name) when matched then update set count = m.count + z.count when not matched then insert (count, name) values (z.count, z.name);
MERGE 4
postgres=# select * from mastertabelle ;
 count |   name   
-------+----------
    70 | thorsten
   260 | tom
   190 | nina
   110 | thomas
(4 rows)

postgres=# select * from zubringertabelle ;
 count | name 
-------+------
(0 rows)

postgres=#

Damit erfülle ich nicht nur die Anforderung des Fragestellers, sondern räume auch noch Deine Bedenken aus dem Weg (bzgl. ob die Aktion schon ausgeführt wurde oder nicht bzw. verhindern, daß sie mehrfach ausgeführt wird)
 
Zurück
Oben