2010-11-18 6 views
37

Beispiel einer Ergebnisspalte in einem Ausdruck wiederverwenden:Wie für eine weitere Ergebnisspalte

SELECT 
    (SELECT SUM(...) FROM ...) as turnover, 
    (SELECT SUM(...) FROM ...) as cost, 
    turnover - cost as profit 

sicher, dies ist ungültig (zumindest in Postgres), sondern, wie man erreicht das gleiche in einer Abfrage ohne Umschreiben die Unterabfrage zweimal?

+0

Hängt von Details wie Spalten und Tabellen ab. –

+0

@OMG Ponis: Wie? Gibt es dafür keinen allgemeinen Weg? – Wernight

+0

Ich stimme @OMG zu. Das heißt, wenn Sie eine * Unterabfrage schreiben können, die sowohl 'Umsatz' als auch 'Kosten' als Spalten zurückgibt, kann die Abfrage, die um diese Unterabfrage gelegt wird, 'Umsatzkosten' ausführen. Für weitere Details benötigen wir einige Details zu Ihrem Schema. –

Antwort

40

Wie so:

SELECT 
    turnover, 
    cost, 
    turnover - cost as profit 
from (
    (SELECT SUM(...) FROM ...) as turnover, 
    (SELECT SUM(...) FROM ...) as cost 
    ) as partial_sums 
+1

Normalerweise, wenn Sie 'table1, table2' auswählen, erhalten Sie den CROSS JOIN der beiden Tabellen. Was wählen Sie aus (table1, table2) als bla (wie Sie hier haben) mit den beiden Tabellen? –

+1

@CharlBotha: Es ist nicht aus wählen (foo, bar). Es ist [wählen] (wählen Sie die Summe aus foo), (wählen Sie die Summe aus der Leiste) [aus dem Nichts]. –

+0

In Ihrem obigen Beispiel haben Sie '... von ((wählen Sie ...) als Umsatz, (wählen Sie ...) als Kosten) als partielle_summen' - ich frage mich immer noch, wie genau der Umsatz und die Kosten Selektionen sind kombiniert? –

4
SELECT turnover, cost, turnover - cost 
FROM 
(
SELECT 
(SELECT ...) as turnover, 
(SELECT ...) as cost 
) as Temp 
+0

Das sind Tabellenaliasnamen, nicht Spaltenaliase ... –

+0

Wenn Umsatz und Kosten Tabellenaliase sind, können Sie dies definitiv nicht tun: Umsatz - Kosten als Profit –

+0

Ungültig: FEHLER: Unterabfrage in FROM muss einen Alias ​​haben TIPP: Beispiel: FROM (SELECT ...) [AS] foo. – Wernight

3

denke ich folgendes funktionieren:

SELECT turnover, cost, turnover-cost as profit FROM 
    (SELECT 1 AS FAKE_KEY, SUM(a_field) AS TURNOVER FROM some_table) a 
INNER JOIN 
    (SELECT 1 AS FAKE_KEY, SUM(a_nother_field) AS COST FROM some_other_table) b 
USING (FAKE_KEY); 

Nicht an Tieren getestet - zunächst wieder! :-)

Teilen und genießen.

4

Eigentlich habe ich viel daran gearbeitet, und viele Mauern getroffen, aber schließlich eine Antwort gefunden - mehr von einem Hack - aber es hat sehr gut funktioniert und den Leseaufwand meiner Abfragen um 90% reduziert. .. Anstatt die korrelierte Abfrage mehrmals zu duplizieren, um mehrere Spalten aus der Unterabfrage zu erhalten, habe ich einfach concat alle Werte verwendet, die ich in ein Komma-getrenntes varchar zurückgeben möchte, und sie dann wieder in der Anwendung abzurollen. So.

statt

select a,b, 
(select x from bigcorrelatedsubquery) as x, 
(select y from bigcorrelatedsubquery) as y, 
(select z from bigcorrelatedsubquery) as z 
from outertable 

ich jetzt

select a,b, 
(select convert(varchar,x)+','+convert(varchar,x)+','+convert(varchar,x)+',' 
from bigcorrelatedsubquery) from bigcorrelatedquery) as xyz 
from outertable 
group by country 

tun habe ich jetzt alle drei korrelierte ‚Skalar‘ Werte, die ich brauchte, hatte aber nur die korrelierte Unterabfrage einmal statt dreimal auszuführen.

+0

Was Sie getan haben sollten, ist 'JOIN' die' bigcorrelatedsubquery' mit 'outtable' einmal, anstatt es mehrmals zu wiederholen oder den concat-Hack zu verwenden. Selbst im schlimmsten Fall hätten Sie diese Unterabfrage als CTE berücksichtigen können, um es nicht zu wiederholen. –

5

Vielleicht ist die SQL "mit" -Klausel, helfen könnte, wie hier dargestellt http://orafaq.com/node/1879 (andere Datenbanken wie Postgres tun es auch, nicht nur Oracle).

+1

Diese Funktion heißt "Common Table Expressions", also CTE. Siehe http://stackoverflow.com/questions/2686919/is-possible-to-reuse-subqueries – Vadzim

10

Sie könnten die Abfrage wie folgt wiederverwenden:

SELECT * 
FROM(
SELECT 
    TURNOVER.sum as SUM_TURNOVER 
FROM 
(
    SELECT SUM(...) FROM ...) 
)AS TURNOVER, 
(
    SELECT SUM(...) FROM ... 
)AS COST 
WHERE .... 
) AS a 

Es gibt einen Punkt hier zu beachten:

WITH 
    TURNOVER AS (
    SELECT SUM(...) FROM ...) 
), 
    COST AS(
    SELECT SUM(...) FROM ... 
) 

SELECT * 
FROM(
SELECT 
    TURNOVER.sum as SUM_TURNOVER 
FROM 
TURNOVER,COST 
WHERE .... 
) AS a 

Dies äquivalent ist. Die erste Methode ist besser lesbar und wiederverwendbar, aber die zweite Methode ist möglicherweise schneller, weil die DB einen besseren Plan dafür wählen könnte.

+0

Dies ist der beste Weg, um den Code mit mehr als einer Unterabfrage lesbar zu machen ... –

0

Sie mit einem Kreuz anwenden oder äußere Anwendung verwenden.

SELECT 
    Calc1.turnover, 
    Calc2.cost, 
    Calc3.profit 
from 
    cross apply ((SELECT SUM(...) as turnover FROM ...)) as Calc1 
    cross apply ((SELECT SUM(...) as cost FROM ...)) as Calc2 

    /* 
    Note there is no from Clause in Calc 3 below. 
    This is how you can "stack" formulas like in excel. 
    You can return any number of columns, not just one. 
    */ 
    cross apply (select Calc1.turnover - Calc2.cost as profit) as Calc3 
0

das ist ziemlich alt, aber ich lief in dieses Problem und sah diesen Beitrag aber didnt verwalten mein Problem mit den gegebenen Antworten zu lösen, so dass ich schließlich zu dieser Lösung gekommen:

, ob Ihre Anfrage ist:

SELECT 
    (SELECT SUM(...) FROM ...) as turnover, 
    (SELECT SUM(...) FROM ...) as cost, 
    turnover - cost as profit 

Sie es in einer Unterabfrage drehen und dann die Felder verwenden, wie zum Beispiel:

SELECT *,(myFields.turnover-myFields.cost) as profit 
FROM 
(  
SELECT 
     (SELECT SUM(...) FROM ...) as turnover, 
     (SELECT SUM(...) FROM ...) as cost 

) as myFields 

Ich bin nicht ganz sicher, ob dies eine schlechte Art ist, Dinge zu tun, aber die Leistung scheint okay für mich Abfrage über 224,000 Aufzeichnungen dauerte 1,5 sec nicht sicher, ob es später in 2x der gleichen Unterabfrage von DB umgewandelt.

Verwandte Themen