Left Join, Gruppierungen und notwendige Aggregationen

pooleleven

Benutzer
Beiträge
8
Hallo Forum. Ich komme aus der MySQL-Welt ... wo vieles nicht ganz eindeutig aber dafür einfacher zu sein scheint ;-) und suche nun in der MSSQL-Welt an der einen oder anderen Stelle bestPractice-Handhabungen.

Habe 2 Tabelle:

Die eine, von der ich alles zeigen möchte:
kontakt_tab
ID-KONTAKT (Key, Unique)NAME
1Bruno
2Ilse
3Irmgard
4Brundhilde

und dann ist da noch eine, aus der nur gelesen werden soll, wenn es übereinstimmung gibt:
descr_tab
ID-DESCR (key, Unique)KONTAKT-ID (Unique)DESCRIPTION
12Beschreibung von Ilse
33Beschreibung von Irmgard

in Mysql würde diese Abfrage eine Lösung liefern:
SQL:
select
kontakt_tab.id-kontakt,
kontakt_tab.name,
descr_tab,description
from kontakt_tab
left join descr_tab on descr_tab.kontakt-id = kontakt_tab.id-kontakt
group by kontakt_tab.id-kontakt

ein sauberes Ergebnis.


ID-KONTAKT (Key, Unique)NAMEDESCRIPTION
1Brunonull
2IlseBeschreibung von Ilse
3IrmgardBeschreibung von Irmgard
4Brundhildenull

MsSQL meldet dagegen "kontakt_tab.name is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause" ... was irgendwie ja auch verständlich ist, weil unter Umständen hier ja mehrere Werte enthalten sein könnten.

Habe mit STRING_AGG (der Wert ist in meinem Beispiel ja immer eindeutig) eine Lösung gebaut ... die ich aber nicht wirklich "schön" finde und die, weil "funktion" sicher auch mal an der Performance nuggelt.

Gibt es in MsSQL hierfür eine "elegante" Lösung?
 
Werbung:
Mysql gibt da ein ungültiges Ergebnis aus, MS SQL hat recht. Jede Spalte in einem SELECT mir GROUP BY muss entweder eine Agregatsfunktion wie zB SUM() sein oder im GROUP BY enthalten sein - alles andere wäre ja auch unlogisch.
 
in Mysql würde diese Abfrage eine Lösung liefern:
SQL:
select
kontakt_tab.id-kontakt,
kontakt_tab.name,
descr_tab,description
from kontakt_tab
left join descr_tab on descr_tab.kontakt-id = kontakt_tab.id-kontakt
group by kontakt_tab.id-kontakt
ein sauberes Ergebnis.
Streng genommen scheint mir das nicht mal eine saubere Abfrage zu sein. Unabhängig von den bekannten mySQL Eigenarten. Komma oder Punkt, ich brauch neue Linsen.
@Walter: Es scheint unlogisch, es gibt aber eine komplexere Logik (oder besser Auswertungsfunktion) dahinter, auch bei anderen Herstellern. Die basiert u.a. auf der Existenz einer (eindeutigen) PK Spalte im Select Teil. Postgres z.B. bietet das auch und macht es dann aber auch richtig. Nur am Rande, ich benutze es auch nicht.

@pooleleven
Für die obige Darstellung benötigst Du gar kein Group by. Die Zeile könntest Du weglassen. Hättest (und wolltest) Du eine Darstellung, in der mehrere Descriptions je Kontakt zusammengefasst angezeigt werden -sofern vorhanden-, dann würdest Du die Beschreibung mit String_agg (weiß nicht wie das unter MSSQL genannt wird) zusammenfassen und ein Group By auf die anderen, nicht aggregierten, aber selektierten Felder anhängen.

Oder anders: wenn man nichts aggregiert, braucht man auch kein Group By und macht vielleicht selbst unter mySQL nichts falsch. Und als Nachtrag, weil es mit dem Titel "Left Join.." überhaupt nicht zu tun hat. Es ist nicht so, dass ein Left Join Hilfe durch Group By braucht oder irgendsowas. Kein Zusammenhang, alle Join Regeln gelten unabhängig von Group By und umgekehrt.
 
Mysql gibt da ein ungültiges Ergebnis aus, MS SQL hat recht. Jede Spalte in einem SELECT mir GROUP BY muss entweder eine Agregatsfunktion wie zB SUM() sein oder im GROUP BY enthalten sein - alles andere wäre ja auch unlogisch.
... stimmt. Aber welche Aggregatfunktion wäre in so einem Fall das Beste? First, Last ... stehen ja nicht zur Verfügung ... und Subselects sind bei so etwas Einfachem ja auch nicht gerade das Gelbe vom Ei. ...zumindest performancetechnisch (hier kann ich aber auch nur von MySQL, Pervasive-Sql.. sprechen)
 
Streng genommen scheint mir das nicht mal eine saubere Abfrage zu sein. Unabhängig von den bekannten mySQL Eigenarten. Komma oder Punkt, ich brauch neue Linsen.
@Walter: Es scheint unlogisch, es gibt aber eine komplexere Logik (oder besser Auswertungsfunktion) dahinter, auch bei anderen Herstellern. Die basiert u.a. auf der Existenz einer (eindeutigen) PK Spalte im Select Teil. Postgres z.B. bietet das auch und macht es dann aber auch richtig. Nur am Rande, ich benutze es auch nicht.

@pooleleven
Für die obige Darstellung benötigst Du gar kein Group by. Die Zeile könntest Du weglassen. Hättest (und wolltest) Du eine Darstellung, in der mehrere Descriptions je Kontakt zusammengefasst angezeigt werden -sofern vorhanden-, dann würdest Du die Beschreibung mit String_agg (weiß nicht wie das unter MSSQL genannt wird) zusammenfassen und ein Group By auf die anderen, nicht aggregierten, aber selektierten Felder anhängen.
stimmt, beim Reintippen habe ich da kommas reingeschmuggelt. Korrigiere ich.
 
stimmt, beim Reintippen habe ich da kommas reingeschmuggelt. Korrigiere ich.
stimmt, beim Reintippen habe ich da ein Komma reingeschmuggelt. Korrigiere ich. Die Linse brauche ich! ;-)
Code:
select
kontakt_tab.id-kontakt,
kontakt_tab.name,
descr_tab.description
from kontakt_tab
left join descr_tab on descr_tab.kontakt-id = kontakt_tab.id-kontakt
group by kontakt_tab.id-kontakt

"Für die obige Darstellung benötigst Du gar kein Group by. " ... wie das immer so mit Beispielen ist.
... erweitern wir das aber mal mit:
KONTAKT-IDTS_VISIT
211.1.1965
212.4.1975
29.11.2011
46.7.1991

Code:
select
kontakt_tab.id-kontakt,
kontakt_tab.name,
descr_tab.description,
count(visit_tab.ts_visit),
max(visit_tab.ts_visit) as last_visit
from
kontakt_tab
left join descr_tab on descr_tab.kontakt-id = kontakt_tab.id-kontakt
left join visit_tab on visit_tab.kontakt-id = kontakt_tab.id-kontakt
group by kontakt_tab.id-kontakt

... dann sieht es schon anders aus ... und wäre korrekter für mein Beispiel gewesen. Es geht aber eben hauptsächlich um Spalten wie "kontakt_tab.name", wie sich hier am performantesten ein eindeutiger Name und vor allem distinct ausgeben lässt.
In MySQL könnte man dies durch group_concat(DISTINCT kontakt_tab.name) erledigen (was ganz nebenbei auch nicht besonders performant ist, vor allem, wenn man das Beispiel mal mit einer echten Kontakttabelle, also mit einer Vielzahl an Spalten realisieren würde).
 
Werbung:
... wie das immer so mit Beispielen ist.
... erweitern wir das aber mal mit:
Naja, Beispiele sind Beispiele. Wenn Du eine Frage stellst, woher soll hier jemand wissen, dass Dein Beispiel eigentlich anders lauten soll. Präzision schadet da weder in der Frage noch in der "sauberen" Umsetzung an der DB.

Und zum Thema group_concat und generell folgender Hinweis:
Wenn du für jede Funktion, die es in MSSQL nicht gibt einen Thread aufmachst, wird es nicht spaßig mit der neuen DB.
Du darfst davon ausgehen, dass das aller aller meiste von mySQL so oder besser oder mehr und besser in anderen DB ebenfalls existiert, nur nicht exakt den gleichen Namen hat.
Mein Vorschlag lautet, einfach im Netz suchen, hier z.B. erster Treffer oder zweiter Treffer:
(ich muss in diesem Fall genau das tun, weil ich weder mySQL noch MS SQL nutze und den Funktionsnamen dort nicht auswendig kenne)
 
Zurück
Oben