philbo20
Goto Top

SQL: 2 Zeilen zu einer zusammenfassen

Hallo zusammen,

ich habe eine SQL-Server 2008 DB, wo ich eine Tabelle mit drei Spalten habe:
Name, Berufswunsch1, Berufswunsch2

Nun ist meistens nur eine Zeile pro Name vorhanden, es ist entweder Berufswunsch1 ODER Berufswunsch2 gefüllt.
Es gibt aber auch einige Namen, die doppelt vorkommen, in der ersten Zeile ist Berufswunsch1 gefüllt, Berufswunsch2 = NULL, in der zweiten Zeile dann Berufswunsch1 = NULL, Berufswunsch2 gefüllt.

Ich würde in einer Abfrage diese gerne in einer Zeile ausgeben lassen, wenn zwei Berufswünsche angegeben sind, dann sollen dies von einem Komma getrennt ausgegeben werden.

Hat jemand eine Idee??

Gruß
Philipp

Content-Key: 246504

Url: https://administrator.de/contentid/246504

Ausgedruckt am: 19.03.2024 um 07:03 Uhr

Mitglied: Gersen
Gersen 14.08.2014 um 15:43:27 Uhr
Goto Top
Hallo,

denkbar vielleicht über die max-Funktion:

select name, max(berufswunsch1), max(berufswunsch2) from tabellenname where name = "xyz";

Ungetestet unter MSSQL...

Gruß,
Gersen
Mitglied: LianenSchwinger
Lösung LianenSchwinger 14.08.2014, aktualisiert am 15.08.2014 um 08:01:37 Uhr
Goto Top
Hallo Gersen,

da fehlt noch die GROUP BY Klausel. face-smile

SELECT name, max(berufswunsch1), max(berufswunsch2) FROM tabellenname GROUP BY by name

G Jörg
Mitglied: philbo20
philbo20 14.08.2014 um 16:09:03 Uhr
Goto Top
Zitat von @LianenSchwinger:

Hallo Gersen,

da fehlt noch die GROUP BY Klausel. face-smile

> SELECT name, max(berufswunsch1), max(berufswunsch2) FROM tabellenname GROUP BY by name
> 

Hallo ihr beiden...

fast face-smile


Also, so klappt es schonmal, dass mir das Ergebnis in drei Spalten ausgegeben wird. Wenn ich allerdings ein Select name, max(berufswunsch1) + ', ' + max(berufswunsch2) versuche, um mir bei zwei Werten diese Kommagetrennt ausgeben zu lassen, dann habe ich fast überall nur NULL stehen.
In den Zeilen, wo beide Berufswünsche gefüllt waren, wird korrekt mit Komma getrennt, allerdings nicht dort, wo nur eine Spalte gefüllt und die andere NULL war.

Wieso??

Danke schonmal!
Mitglied: LianenSchwinger
LianenSchwinger 14.08.2014 um 16:33:51 Uhr
Goto Top
Hallo,

ganz einfach ein "irgendwas" + NULL = NULL

Was gefällt Dir an der 3 Spalten Lösung denn nicht?

G Jörg
Mitglied: Biber
Biber 14.08.2014, aktualisiert am 15.08.2014 um 09:33:45 Uhr
Goto Top
Moin philbo20,

so in etwa (ungetestet):

SELECT name
    ,   case when bw1 is null then '' else bw1 ||', ' end  
     || case when bw2 is null then '' else bw2       end   
      as bw 
  FROM  (   
 SELECT name, max(berufswunsch1) as bw1, max(berufswunsch2) as bw2 
  FROM tabellenname GROUP BY by name 
) x
;

[/Edit]

Alternativ kannst du die NULL-Werte mit COALESCE() oder ISNULL() zu Wunschwerten umwandeln.

Das Statement funktioniert aber - unabhängig von NULL-Werten- auch nur unter den von dir vorgefundenen Gegebenheiten.
Sprich - es gibt keinen Fall, in dem für einen Namen mal mehrere "berufswunsch1" oder mehrere "berufswunsch2"-Felder gefüllt sind.

Falls also irgendein Depp eingegeben hat
Name="Depp", berufswunsch1="Millionär", berufswunsch2=NULL
Name="Depp", berufswunsch1="Zwiebelschäler", berufswunsch2="Fleckentferner"

--> dann fällt durch die MAX()-Aggregatfunktion der eigentlich sicherlich präferierte Berufswunsch ganz raus aus jeglichem Resultset.

Grüße
Biber
Mitglied: philbo20
philbo20 15.08.2014 aktualisiert um 08:11:30 Uhr
Goto Top
Danke euch!
ich habe es noch ein wenig angepasst, und hoffe nun alle eventualitäten abzufangen (beide Spalten sind nie Null, daher habe ich das nicht abgefragt).
SELECT name,   
CASE WHEN (bw1 IS not null and bw2 is not null) then (bw1 + ', '+ bw2)   
ELSE (CASE WHEN bw1 IS not null then bw1 ELSE bw2 END) END AS 'Berufswunsch'    
FROM  (   
 SELECT name, max(berufswunsch1) as bw1, max(berufswunsch2) as bw2 
  FROM BewProf GROUP BY name
) x
;
So funktioniert das Ganze auf jeden Fall!

Ich muss es in 1 Spalte zusammenfassen, weil ich es so für die weitere Verwendung liefern muss.
Eigentlich hätte ich wahrscheinlich, um es sauber zu lösen, schon eine Ebene höher ansetzen müssen. Ich lasse mir die Werte aus einer Tabelle mittels SSIS in 2 nacheinander ausgeführten SQL-Abfragen (eine für Berufswunsch 1, eine für Berufswunsch2) in eine neue Tabelle schreiben. Allerdings müsste die zweite Abfrage ja eigentlich wenn der Name schon vorhanden ist, nur die Spalte Berufswunsch2 füllen, anstatt eine neue Zeile anzufügen. Das hab ich aber nicht hingekriegt...

also falls jemand weiß, wie ich das löse face-smile
Mitglied: Biber
Biber 15.08.2014 aktualisiert um 09:41:54 Uhr
Goto Top
Moin philbo,

bei deiner Strategie kannst du das Statement mit der o.a. COALESCE-Funktion noch ewas schlanker gestalten:
SELECT name,   
CASE WHEN (bw1 IS not null and bw2 is not null) THEN (bw1 + ', '+ bw2)   
         ELSE (COALESCE(  bw1 , bw2 ) END AS 'Berufswunsch'    
FROM  (   
 SELECT name, max(berufswunsch1) as bw1, max(berufswunsch2) as bw2 
  FROM BewProf GROUP BY name
) x
;

Zu deiner neuen Frage:
Ich würde gar nicht erst zwei SQL-Statements gegen das SSIS schiessen, sondern nur eine Abfrage, die Berufswunsch1 und Berufswunsch2 holt.
Oder ist das nicht möglich mit den Abfragemöglichkeiten, die dir SSIS bietet?

Poste doch mal die beiden Statements (zumindest sinngemäß).

Grüße
Biber
Mitglied: Gersen
Gersen 15.08.2014 aktualisiert um 10:02:33 Uhr
Goto Top
Zitat von @philbo20:
Eigentlich hätte ich wahrscheinlich, um es sauber zu lösen, schon eine Ebene höher ansetzen müssen. Ich lasse
mir die Werte aus einer Tabelle mittels SSIS in 2 nacheinander ausgeführten SQL-Abfragen (eine für Berufswunsch 1, eine
für Berufswunsch2) in eine neue Tabelle schreiben. Allerdings müsste die zweite Abfrage ja eigentlich wenn der Name
schon vorhanden ist, nur die Spalte Berufswunsch2 füllen, anstatt eine neue Zeile anzufügen. Das hab ich aber nicht
hingekriegt...

also falls jemand weiß, wie ich das löse face-smile

Dazu solltest Du Dir vielleicht mal das MERGE-Konstrukt anstelle von einfachen INSERTs anschauen.
Mitglied: philbo20
philbo20 15.08.2014 um 10:00:41 Uhr
Goto Top
Ja, wenn ich beide Statements in einer Abfrage unterbringen könnte, so dass die Ergebnisse in eine Zeile (bei gleichem Namen) geschrieben werden, wäre das natürlich Ideal...
also hier meine Abfragen:
SELECT Name, MIN(tPersBewProfBkz.tPpbBkz) AS ErsterWertvontPpbBkz_baus 
FROM tPersBewProf INNER JOIN tPersBewProfBkz ON tPersBewProf.tBpId = tPersBewProfBkz.tPpbBpId 
WHERE (((tPersBewProf.tBpStellenTyp)='baus') AND ((tPersBewProf.tBpAktAb)<=Convert(date,GetDate())   
AND ((tPersBewProf.tBpAktBis)>=Convert(date,GetDate()) Or (tPersBewProf.tBpAktBis) Is Null) 
GROUP BY Name
und Abfrage 2:
SELECT Name, MIN(tPersBewProfBkz.tPpbBkz) AS ErsterWertvontPpbBkz_aarb 
FROM tPersBewProf INNER JOIN tPersBewProfBkz ON tPersBewProf.tBpId = tPersBewProfBkz.tPpbBpId 
WHERE (((tPersBewProf.tBpStellenTyp)='aarb') AND ((tPersBewProf.tBpAktAb)<=Convert(date,GetDate())   
AND ((tPersBewProf.tBpAktBis)>=Convert(date,GetDate()) Or (tPersBewProf.tBpAktBis) Is Null) 
AND ((tPersBewProfBkz.tPpbPrio)=-1) AND ((tPersBewProfBkz.tPpbBkz)<>'99999999')))  
GROUP BY Name

vom Prinzip her sind beide identisch, der einzige Unterschied ist die Where-Bedingung in Bezug auf das Feld Stellentyp.
Mitglied: Biber
Lösung Biber 15.08.2014, aktualisiert am 18.08.2014 um 15:06:19 Uhr
Goto Top
Moin philbo20,

dann würde ich einfach die beiden Statements in einem UNION ALL zusammenfassen (jeweils mit einem Dummywert für das nicht abgefragte Feld), danch nachmal aggregieren und fertsch.

Select Name
     , Max(ErsterWertvontPpbBkz_baus) as ErsterWertvontPpbBkz_baus
     , Max( ErsterWertvontPpbBkz_aarb) as ErsterWertvontPpbBkz_aarb 
    FROM (  
SELECT Name, 
   MIN(tPersBewProfBkz.tPpbBkz) AS ErsterWertvontPpbBkz_baus , '' as ErsterWertvontPpbBkz_aarb  
FROM tPersBewProf 
 INNER JOIN tPersBewProfBkz ON tPersBewProf.tBpId = tPersBewProfBkz.tPpbBpId 
 WHERE (((tPersBewProf.tBpStellenTyp)='baus') AND ((tPersBewProf.tBpAktAb)<=Convert(date,GetDate())   
 AND ((tPersBewProf.tBpAktBis)>=Convert(date,GetDate()) Or (tPersBewProf.tBpAktBis) Is Null) 
GROUP BY Name
UNION ALL
SELECT Name, '' as ErsterWertvontPpbBkz_baus , MIN(tPersBewProfBkz.tPpbBkz) AS ErsterWertvontPpbBkz_aarb   
FROM tPersBewProf 
 INNER JOIN tPersBewProfBkz ON tPersBewProf.tBpId = tPersBewProfBkz.tPpbBpId 
 WHERE (((tPersBewProf.tBpStellenTyp)='aarb') AND ((tPersBewProf.tBpAktAb)<=Convert(date,GetDate())   
 AND ((tPersBewProf.tBpAktBis)>=Convert(date,GetDate()) Or (tPersBewProf.tBpAktBis) Is Null) 
AND ((tPersBewProfBkz.tPpbPrio)=-1) AND ((tPersBewProfBkz.tPpbBkz)<>'99999999')))  
GROUP BY Name
) x
GROUP BY Name
;

Ich habe jetzt inhaltlich nicht weiter draufgeschaut, ob sich das evtl ohne UNION und mit einem Zugriff auf die tPersBewProf-Tabelle lösen liesse mit einer WHERE ( (.....baus-Bedingung) OR (aarb-Bedingung) ).

Kannst ja erstmal probieren, ob dieses Statement in endlicher Zeit fertig wird..

Grüße
Biber
Mitglied: philbo20
philbo20 18.08.2014 um 15:10:38 Uhr
Goto Top
Hi...
danke, hab es jetzt mit dem Union in der Abfrage gelöst und mache dann direkt danach ein Update, wo ich die beiden Werte dann kommagetrennt in ein drittes Feld schreiben lasse.

Gruß
Philipp