Rolf b: mysql: Kompliziertes SQL-Problem

Beitrag lesen

Vielleicht wird es ja mit einem Tabellenausdruck im FROM und einem UNION ALL übersichtlicher?

-- Variante A
SELECT SUM((CASE WHEN tab.Menge = 0 THEN 1 ELSE tab.Menge) * Preis)
FROM ( 
       SELECT a.MengeA AS Menge, a.PreisA AS Preis
       FROM tab_b A
       WHERE a.A_B = 'A' AND (a.MengeA > 0 OR a.Art NOT IN ('AZ', 'AK'))
     UNION ALL
       SELECT b.MengeB AS Menge, b.PreisB AS Preis
       FROM tab_b B
       WHERE b.A_B = 'B' AND (b.MengeB > 0 OR b.Art NOT IN ('AZ', 'AK'))
     ) tab

-- Variante B
SELECT SUM((CASE WHEN tab.Menge = 0 THEN 1 ELSE tab.Menge) * Preis)
FROM ( 
       SELECT a.MengeA AS Menge, a.PreisA AS Preis FROM tab_b A WHERE a.A_B = 'A'
     UNION ALL
       SELECT b.MengeB AS Menge, b.PreisB AS Preis FROM tab_b B WHERE b.A_B = 'B'
     ) tab
WHERE tab.Menge > 0 OR tab.Art NOT IN ('AZ', 'AK')

Ich wusste jetzt nicht, ob tab_b ein Tabellenname oder ein Alias ist; ich bin mal von einem Tabellennamen ausgegangen. Ob die Aliase A und B nötig sind, müsste man ausprobieren; sie können nicht schaden. Der Alias tab ist auf jeden Fall nötig.

Im FROM werden zwei SELECT-Mengen kombiniert. Für A_B='A' wird MengeA und PreisA ausgewählt, für A_B='B' MengeB und PreisB. Der äußere SELECT kann dann die gefundenen Mengen und Preise aufsummieren, ohne auf A_B achten zu müssen.

Die WHERE Klausel lässt nur die Sätze durch, die entweder eine Menge > 0 haben oder dann, wenn die Menge 0 ist, nicht die Art AZ oder AK haben. Das entspricht deiner "Lösung", bei Menge=0 und Art AZ oder AK den Preis mit 0 zu multiplizieren, sprich: nicht zu summieren.

Ob man diesen Filter an den inneren SELECTs (Variante A) oder in einem eigenen WHERE im äußeren SELECT (Variante B) notiert, sollte vom Ergebnis her egal sein. Ich vermute, dass Variante A schneller ist, weil früher gefiltert wird. Müsste man EXPLAINen oder nachmessen.

Rolf