2016-08-04 56 views
0

Ich habe folgende vereinfachte Abfrage:Mysql Wiederverwendung von Summen von Unterabfragen

Select 
(select sum(f1) from tableA a where a.id = t.id) sum1, 
(select sum(f2) from tableB b where b.id = t.id) sum2, 
t.* 
from Table t; 

Mein Wunsch ist sum1 und sum2 wieder verwendet haben, ohne sie erneut Berechnung:

Select 
(select sum(f1) from tableA a where a.id = t.id) sum1, 
(select sum(f2) from tableB b where b.id = t.id) sum2, 
sum1 + sum2 `sum3`,  
t.* 
from Table t; 

Natürlich i die folgende Abfrage, aber das wird nicht notwendig die doppelte Laufzeit tun kann:

Select 
(select sum(f1) from tableA a where a.id = t.id) sum1, 
(select sum(f2) from tableB b where b.id = t.id) sum2, 
(select sum(f1) from tableA a where a.id = t.id) + 
(select sum(f2) from tableB b where b.id = t.id) `sum3`,  
t.* 
from Table t; 

oder sogar die sum1 und sum2 res Einsetzen ults zu einer temporären Tabelle aber kann nicht imaging Ich übersehe etwas, um mysql eine effiziente Abfrage von summierten Feldern zu machen.

Gibt es eine bessere, effizientere Möglichkeit, summierte Felder wiederzuverwenden?

Antwort

1

Diese Abfrage ausgeführt wird,

select Resutl.*,Result.sum1+Result.sum2 as sum3 from(
     SELECT (SELECT SUM(f1) FROM tableA a WHERE a.id = t.id) sum1, 
       (SELECT SUM(f2) FROM tableB b WHERE b.id = t.id) sum2, 
       t.* 
     FROM Table t)Result 
) 

Hoffe, es hilft.

0

Mein Wunsch ist sum1 und sum2 haben

Whoa ohne Berechnung sie wieder wiederverwendet werden, stetig an. Die ursprüngliche Abfrage ist nicht so effizient wie es sein könnte. Ohne zu wissen, wie die Datenverteilung aussieht, ist es schwierig zu sagen, was die geeignetste Abfrage ist, aber angenommen, dass die Tupel in A und B eine Fremdschlüsseleinschränkung (implizit oder explizit) in Tabelle T, aber keine implizite Fremdschlüsseleinschränkung haben , dass t.id ist einzigartig, und die meisten der Zeilen in Form von Tabletten haben entsprechende Zeilen in tableA und tableB dann ....

SELECT t.*, sum_f1, sum_f2 
FROM tableT t 
LEFT JOIN (SELECT a.id, SUM(f1) AS sum_f1 
FROM tableA a 
GROUP BY a.id) AS a_agg 
ON t.id=a_agg.id 
LEFT JOIN (SELECT b.id, SUM(f2) AS sum_f2 
FROM tableB b 
GROUP BY b.id) as b_agg 
ON t.id=b_agg.id 
GROUP BY t.id 

wird viel effizienter sein. (Dies setzt auch voraus, dass ONLY_FULL_GROUP_BY deaktiviert ist - andernfalls müssen Sie 't. *' In der SELECT-Klausel und 't.id' in der group by-Klausel mit jedem der benötigten Attribute aus der Tabelle ersetzen).

Beachten Sie, dass Sie in der Praxis selten alle Ihre Daten in einer einzigen Abfrage betrachten werden. Da MySQL Push-Vergleichselemente nicht gut beherrscht, ist das Hinzufügen eines Filters im äußeren SELECT wahrscheinlich nicht die optimale Lösung.

Nachdem Sie Ihre Abfrage wie oben aufgebaut haben, ist es trivial die Summen hinzuzufügen:

SELECT t.*, sum_f1, sum_f2, 
IFNULL(sum_f1,0)+INFULL(sum_f2,0) AS sum3 
FROM tableT t 
LEFT JOIN (SELECT a.id, SUM(f1) AS sum_f1 
FROM tableA a 
GROUP BY a.id) AS a_agg 
ON t.id=a_agg.id 
LEFT JOIN (SELECT b.id, SUM(f2) AS sum_f2 
FROM tableB b 
GROUP BY b.id) as b_agg 
ON t.id=b_agg.id 
GROUP BY t.id 

(aber beachten Sie, dass ich ein viel gemacht haben von Annahmen über Ihre Daten und Schema)