Select-Abfrage von 2 Werten mit unterschiedlichen Bedingungen möglich?

Ramki

Benutzer
Beiträge
8
Hallo liebe Forumsmitglieder,

ich stehe mit SQL noch ziemlich am Anfang. Einfache Select, Insert oder Update-Befehle bekomme
ich gerade so hin ... :)

Jetzt stehe ich vor einem Problem, bei dem ich nicht weiterkomme:
Ich hab eine Basistabelle mit den Spalten Kunde, Szenario, Jahr und Wert. Darauf möchte ich gerne
eine Selektion, gruppiert nach 'Kunde' ausführen, die mir als Ergebnis 2 Werte nebeneinander (zum
Vergleich) ausgibt, also z.B. 'Ist 2015' und 'Budget 2016'.
Geht das irgendwie mit einer "verschachtelten Select-Anweisung" oder muss man mit CREATE tabel
temporär neue Tabellen erzeugen?

Anbei nochmal die Tabellenstruktur und das gewünschte Abfrageergebnis zur Veranschaulichung.
Freue mich auf Tipps/Unterstützung.

Vielen Dank, Ramki

Tabelle:
Kunde ......... Szenario ..... Jahr .....Wert
Kunde_A .... Ist ............... 2015 ...... 15
Kunde_A .... Budget ....... 2015 ...... 10
Kunde_B .... Budget ....... 2016 ...... 8
Kunde_C .... Ist ............... 2015 ...... 20
Kunde_B .... Ist ............... 2016 ...... 12
Kunde_A .... Ist ............... 2016 ...... 15
Kunde_B .... Ist ............... 2015 ...... 10
Kunde_C .... Budget ....... 2016 ...... 10
Kunde_C .... Ist ............... 2015 ...... 20

Gewünschtes Abfrage-Ergebnis:

..................................... (1.Wert = Ist 2015) ..... (2. Wert = Budget 2016)
Kunde_A ..................... 15 ................................ 0
Kunde_B .....................10 ................................. 8
Kunde_C .....................40 ................................ 10
 
Werbung:
Moin,

möglicherweise geht das mit Deiner DB nicht:

Code:
test=*# select * from ramki ;
 kunde | szenario | jahr | wert
-------+----------+------+------
 a  | i  | 2015 |  15
 a  | b  | 2015 |  10
 b  | b  | 2016 |  8
 c  | i  | 2015 |  20
 b  | i  | 2016 |  12
 a  | i  | 2016 |  15
 b  | i  | 2015 |  10
 c  | b  | 2016 |  10
 c  | i  | 2015 |  20
(9 rows)

test=*# select kunde, sum(wert) filter (where jahr = 2015 and szenario = 'i'), sum(wert) filter (where jahr=2016 and szenario = 'b') from ramki group by kunde order by kunde;
 kunde | sum | sum
-------+-----+-----
 a  |  15 |   
 b  |  10 |  8
 c  |  40 |  10
(3 rows)

falls das nicht geht: subselects. Ist halt dann teurer, weil 2 Scans durch die Tabelle gehen.
 
hier ein weg, der auch bei nicht so leistungsfähigen Datenbanken wie PostgreSQL funktionieren sollte:

Code:
test=*# select distinct r.kunde, s1.sum, s2.sum from ramki r left join (select kunde, sum(wert) from ramki where jahr = 2015 and szenario = 'i' group by kunde) s1 on r.kunde=s1.kunde left join (select kunde, sum(wert) from ramki where jahr = 2016 and szenario = 'b' group by kunde) s2 on r.kunde=s2.kunde order by kunde;
 kunde | sum | sum
-------+-----+-----
 a  |  15 |   
 b  |  10 |  8
 c  |  40 |  10
(3 rows)
 
und kürzer dafür aber schöner:

Code:
test=*# select s1.kunde, s1.sum as "1.Wert Ist 2015", s2.sum as "2. Wert Budget 2016" from (select kunde, sum(wert) from ramki where jahr = 2015 and szenario = 'i' group by kunde) s1 left join (select kunde, sum(wert) from ramki where jahr = 2016 and szenario = 'b' group by kunde) s2 on s1.kunde=s2.kunde order by s1.kunde;
 kunde | 1.Wert Ist 2015 | 2. Wert Budget 2016
-------+-----------------+---------------------
 a  |  15 |   
 b  |  10 |  8
 c  |  40 |  10
(3 rows)
 
Hallo akretschmer,

ganz lieben Dank für die Mühe, die Du dir gemacht hast. Ich habe alle 3 Lösungsansätze ausprobiert. Leider will nichts so recht funktionieren.

Ich erhalte folgende Fehler:

1. Möglichkeit (Die mit 'filter' = für mich am einfachsten nachvollziehbar):
Incorrect syntax near the keyword 'where'.

2. Möglichkeit (mit select distinct):
No column name was specified for column 2 of 's1'.
No column name was specified for column 2 of 's2'.


3. Möglichkeit (mit einfügen von Spaltentiteln):
No column name was specified for column 2 of 's1'.
No column name was specified for column 2 of 's2'.
Invalid column name 'sum'.

Invalid column name 'sum'.


Was mache ich denn bloß falsch?

Danke, Gruß,
Ramki

PS: Ich bin auf dem MS SQL Server 2012 unterwegs ...
 
1. ist sicher die schönste Version, das kann aber wohl wirklich nur PostgreSQL, weil es die weltbeste Datenbank halt ist ;-)

2. und 3. mußt halt mal sehen, daß Du den Spalten noch Aliase gibst. Zum beispiel der Spalte, die die Summe enthält. Bei PG bekommt die Spalte den Namen der Funktion, die diese erzeugt hat - hier sum(). Das mag in anderen Systemen so nicht gehen oder anders halt sein.
 
probier mal so, ob das hilft. das dürfte 3.) lösen:

Code:
test=*# select s1.kunde, s1.x as "1.Wert Ist 2015", s2.x as "2. Wert Budget 2016" from (select kunde, sum(wert) as x from ramki where jahr = 2015 and szenario = 'i' group by kunde) s1 left join (select kunde, sum(wert) as x from ramki where jahr = 2016 and szenario = 'b' group by kunde) s2 on s1.kunde=s2.kunde order by s1.kunde;
 kunde | 1.Wert Ist 2015 | 2. Wert Budget 2016
-------+-----------------+---------------------
 a  |  15 |   
 b  |  10 |  8
 c  |  40 |  10
(3 rows)

Noch mal 'just for fun' die Ausführungspläne dafür und für die Filter-Variante:

Code:
test=*# explain select s1.kunde, s1.x as "1.Wert Ist 2015", s2.x as "2. Wert Budget 2016" from (select kunde, sum(wert) as x from ramki where jahr = 2015 and szenario = 'i' group by kunde) s1 left join (select kunde, sum(wert) as x from ramki where jahr = 2016 and szenario = 'b' group by kunde) s2 on s1.kunde=s2.kunde order by s1.kunde;
  QUERY PLAN   
-------------------------------------------------------------------------------
 Sort  (cost=2.35..2.36 rows=1 width=18)
  Sort Key: ramki.kunde
  ->  Nested Loop Left Join  (cost=2.29..2.34 rows=1 width=18)
  Join Filter: (ramki.kunde = ramki_1.kunde)
  ->  HashAggregate  (cost=1.15..1.16 rows=1 width=6)
  Group Key: ramki.kunde
  ->  Seq Scan on ramki  (cost=0.00..1.14 rows=3 width=6)
  Filter: ((jahr = 2015) AND (szenario = 'i'::text))
  ->  HashAggregate  (cost=1.14..1.15 rows=1 width=6)
  Group Key: ramki_1.kunde
  ->  Seq Scan on ramki ramki_1  (cost=0.00..1.14 rows=1 width=6)
  Filter: ((jahr = 2016) AND (szenario = 'b'::text))
(12 rows)

test=*# explain select kunde, sum(wert) filter (where jahr = 2015 and szenario = 'i'), sum(wert) filter (where jahr=2016 and szenario = 'b') from ramki group by kunde order by kunde;  QUERY PLAN   
------------------------------------------------------------------
 Sort  (cost=1.30..1.31 rows=3 width=12)
  Sort Key: kunde
  ->  HashAggregate  (cost=1.25..1.28 rows=3 width=12)
  Group Key: kunde
  ->  Seq Scan on ramki  (cost=0.00..1.09 rows=9 width=12)
(5 rows)

Eindeutig, oder? (die Kosten sind hier bei der sehr kleinen Tabelle natürlich irrelevant und nicht wirklich vergleichbar, aber der Plan schon)
 
Werbung:
was mir grad noch einfällt: du kannst auch das mit dem FILTER nachbauen, in etwa so:

aus:
sum(wert) filter (where jahr = 2015 and szenario = 'i'),

machst du:
sum(case when jahr = 2015 and szenario = 'i' then wert else 0 end) as ...


Sollte auch mit Datenbanken gehen, die nicht so clever wie PG sind ...
 
Zurück
Oben