Variablen in der SELECT-Abfrage

carstenkunz

Benutzer
Beiträge
5
Ich möchte in einer Abfrage per SELECT...FROM relativ aufwendige Terme benutzen, die eine Berechnung aus mehreren Datenfeldern der Datensätze enthalten. Die Abfrage beinhaltet mehrere Spalten, in denen immerwieder derselbe Term auftaucht. Diesen Term möchte ich durch einen Platzhalter ersetzen, den ich zentral an einer Stelle editieren kann. Eine lokale Variable @test eignet sich nicht dafür, da sie nicht in ein Abfragekonstrukt eingebunden werden kann, sondern maximal in einer separaten SELECT-Schleife. Dann wird aber nur der letzte Wert übernommen. Wie könnte eine Lösung meines Problems aussehen. Anbei ein Beispiel fürs bessere Verständnis:

Select
(a+b)/c * 100 as 'Formel 1'
(a+b)/c + d as 'Formel 2'
(a+b)/c * (a+b)/c as 'Formel 3'
From...

wobei ich (a+b)/c gern durch einen Platzhalter ersetzen möchte, der an einer Stelle definiert wird. In meinem realen Problem benötige ich mehrere Platzhalter und das Konstrukt enthält case-when-Strukturen, sodass es nicht mehr so übersichtlich darstellbar ist, was ja auch mein Problem ist.
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.028
Select
(a+b)/c * 100 as 'Formel 1'
(a+b)/c + d as 'Formel 2'
(a+b)/c * (a+b)/c as 'Formel 3'
From...

wobei ich (a+b)/c gern durch einen Platzhalter ersetzen möchte, der an einer Stelle definiert wird. In meinem realen Problem benötige ich mehrere Platzhalter und das Konstrukt enthält case-when-Strukturen, sodass es nicht mehr so übersichtlich darstellbar ist, was ja auch mein Problem ist.


select bla * 100 as "Formel 1", bla +d as "Formel 2" from (select (a+b)/c from table) blub;
 

carstenkunz

Benutzer
Beiträge
5
Du meinste select bla * 100 as "Formel 1", bla +d as "Formel 2" from (select (a+b)/c AS bla from table) blub;

Super Anregung ! Dass man per Verkettung nach FROM die Tabelle für seine Abfrage quasi nach Belieben formen kann, war mir nicht klar. Danke. In meinem realen Problem muss ich dies in zwei Schritten tun, da bla2 leider von bla1 abhängt und ich in der finalen Abfrage sowohl a, b und c, als auch bla1 und bla2 brauche. Wenn ich Probleme damit habe, melde ich mich :)
 

carstenkunz

Benutzer
Beiträge
5
Super Anregung ! Dass man per Verkettung nach FROM die Tabelle für seine Abfrage quasi nach Belieben formen kann, war mir nicht klar. Danke. In meinem realen Problem muss ich dies in zwei Schritten tun, da bla2 leider von bla1 abhängt und ich in der finalen Abfrage sowohl a, b und c, als auch bla1 und bla2 brauche. Wenn ich Probleme damit habe, melde ich mich :)


ok, da ist es schon: mit "...from (select....as....from...) blub;" baue ich mir eine neue Tabelle, aber leider sind die Felder von blub nicht mehr zugänglich, geht auch irgendwie "...from blub + (select...as...from blub)", damit ich quasi die Tabelle um Spalten erweitere, die sich aus den vorhandenen Spalten errechnen, ich in der Abfrage aber auf alle Felder zugreifen kann ?
 

akretschmer

Datenbank-Guru
Beiträge
9.028
ok, da ist es schon: mit "...from (select....as....from...) blub;" baue ich mir eine neue Tabelle, aber leider sind die Felder von blub nicht mehr zugänglich, ?

Das sollte aber gehen:

Code:
test=# select * from foo;
id |        val
----+--------------------
  1 | 0.0639356011524796
  2 |  0.912768886424601
  3 |  0.76917368452996
  4 |  0.636061595752835
  5 |  0.613543073646724
  6 |  0.526887810323387
  7 |  0.227902846876532
  8 |  0.650828402023762
  9 |  0.278164415620267
10 |  0.981419377960265
(10 rows)

Time: 80,348 ms
test=*# select x from (select id, val as x from foo) blub;
        x
--------------------
0.0639356011524796
  0.912768886424601
  0.76917368452996
  0.636061595752835
  0.613543073646724
  0.526887810323387
  0.227902846876532
  0.650828402023762
  0.278164415620267
  0.981419377960265
(10 rows)

Time: 14,950 ms
test=*#
 

ukulele

Datenbank-Guru
Beiträge
4.394
ok, da ist es schon: mit "...from (select....as....from...) blub;" baue ich mir eine neue Tabelle, aber leider sind die Felder von blub nicht mehr zugänglich, geht auch irgendwie "...from blub + (select...as...from blub)", damit ich quasi die Tabelle um Spalten erweitere, die sich aus den vorhandenen Spalten errechnen, ich in der Abfrage aber auf alle Felder zugreifen kann ?

Von den Informationen die du in deinem äußeren Select brauchst solltest du soviele wie möglich aus dem inneren Select übergeben. Den Rest kannst du einfach dazu joinen. Von einem Subselect würde ich abraten, das wird langsam.
 

carstenkunz

Benutzer
Beiträge
5
Das sollte aber gehen:

Code:
test=# select * from foo;
id |        val
----+--------------------
  1 | 0.0639356011524796
  2 |  0.912768886424601
  3 |  0.76917368452996
  4 |  0.636061595752835
  5 |  0.613543073646724
  6 |  0.526887810323387
  7 |  0.227902846876532
  8 |  0.650828402023762
  9 |  0.278164415620267
10 |  0.981419377960265
(10 rows)
 
Time: 80,348 ms
test=*# select x from (select id, val as x from foo) blub;
        x
--------------------
0.0639356011524796
  0.912768886424601
  0.76917368452996
  0.636061595752835
  0.613543073646724
  0.526887810323387
  0.227902846876532
  0.650828402023762
  0.278164415620267
  0.981419377960265
(10 rows)
 
Time: 14,950 ms
test=*#


ja so hab ich es im Moment realisiert. Da es sich aber um viele Felder handelt, die ich von innen nach außen übergeben muss, hatte ich die Hoffnung, dass es so funktioniert: "select .... from foo,(select <formel1> as x, <formel2> as y from foo) blub;

...Aber leider setzt er die Teile nicht einfach nebeneinander (foo,x und y), sondern kreuzt sie irgendwie.
 

carstenkunz

Benutzer
Beiträge
5
Nachdem ihr mir schon super weitergeholfen habt, darf ich mein Folgeproblem noch einmal auf das wesentliche reduzieren ?? :

Statt der Abfrage

Select
...
From
PROJECTS

möchte ich jetzt aus einer Tabelle auswählen, die zusätzlich zu PROJECTS noch eine Spalte besitzt, die sich aus den Spalten von PROJECTS errechnet. Meine Hoffnung war, dass folgendes funktioniert (a, b und c sind Spalten von PROJECTS, d die neue Spalte):

Select
...
From
PROJECTS,
(select a+b+c as d from PROJECTS)

Das funktioniert aber nicht, da in dieser Konstellation nicht einfach d als neue Spalte hinzugefügt wird, sondern jede Zeile von PROJECTS mit jeder Zeile von d neu kombiniert wird. Als Lösung muss ich bis jetzt folgendes kompliziertes Konstrukt verwenden:

Select
...
From
(select
a, b, c, a+b+c as d from PROJECTS)

Das sieht gar nicht komplizierter aus, ist es aber, wenn ich a, b, c und d durch reale Terme ersetze und noch eine Unterabfrage hinzufüge, die von a, b, c und d abhängt. Gibt es also eine Verknüpfung zwischen einer Tabelle und weiteren Spalten, die an dieser Stelle neben der Ursprungsdatenbank angeordnet wird ??
 

akretschmer

Datenbank-Guru
Beiträge
9.028
Nachdem ihr mir schon super weitergeholfen habt, darf ich mein Folgeproblem noch einmal auf das wesentliche reduzieren ?? :

Statt der Abfrage

Select
...
From
PROJECTS

möchte ich jetzt aus einer Tabelle auswählen, die zusätzlich zu PROJECTS noch eine Spalte besitzt, die sich aus den Spalten von PROJECTS errechnet. Meine Hoffnung war, dass folgendes funktioniert (a, b und c sind Spalten von PROJECTS, d die neue Spalte):

Meinst Du mit 'auswählen' daß das in die WHERE-Condition kommt? Dann schreib Deine Formel da einfach hin.

Achtung: das endet dann aber in einem Full-Table-Scan, es sei denn, Du hast einen funktionalen Index.
 
Werbung:

ukulele

Datenbank-Guru
Beiträge
4.394
Eigentlich haßt du schon den leichtesten Weg gewählt. Es gibt noch zwei andere, schnelle Wege die Informationen zu ergänzen:
Code:
SELECT    t1.a,
        t1.b,
        t1.c,
        t2.d
FROM    tabelle t1
LEFT JOIN tabelle t2 ON t1.id = t2.id
Du joinst die 2te Tabelle anhand einer eindeutigen Datensatz ID, die du hoffentlich hast. Ansonsten kannst du theoretisch auch t1.a = t2.a AND t1.b = t2.b nehmen, das ist natürlich umständlicher. Vom prinzip her ist das aber wie deine Abfrage (ein FULL JOIN) nur eben werden nicht alle Einträge mit allen anderen in Relation gesetzt.
Code:
SELECT    t1.a,
        t1.b,
        t1.c,
        t2.d
FROM    tabelle t1,
        (    SELECT    a+b+c AS d
            FROM    tabelle ) t2
WHERE t1.id = t2.id
Auch möglich, aber eigentlich nur ne andere Schreibweise deines Codes.
 
Oben