In SQL-Select bestimmte Wertelabels anzeigen lasse

Liebe/-r Experte/-in,

Folgender Sachverhalt:

Ich möchte aus einer SQL Datenbank einen SELECT machen. Diese Datenbank besteht häufig aus INT-Codes. Diesen Codes sind jedoch eigentlich bestimmte Werte zugeordnet, z.B. 1001=Männlich, 1002 = Weiblich.

Wenn ich nun den SQL Select mache werden logischerweise nur die Codes ausgegeben, nicht jedoch der dazugehörige Wert. Ich wollte daher wissen ob es eine Möglichkeit gibt im SELECT-Befehl selbst die dazugehörigen Werte zuzuordnen, so dass ich in der Ausgabe-Tabelle schlussendlich nicht die Codes habe, sodern eben die Labels. Also zum Beispiel:

1 Weiblich
2 Weiblich
3 Männlich
4 Weiblich

statt

1 1002
2 1002
3 1001
4 1002

Gibt es in einem SELECT die Möglichkeit dies so umzusetzen?

Vielen Dank im Voraus für die Hilfe!

Hallo liebe/r Toonia,

selbstverständlich gibt es diese Möglichkeit.

Am saubersten wäre meiner Meinung nach eine extra Stammdatentabelle in der man zu den Codes einen Textwert hinterlegt und diesen dann mittels eines Joins im Select anzeigt.
Also z.b. eine Tabelle mit zwei Spalten (Spalte Code und Spalte Text) mit den Datensätzen 1001, männlich und 1002, weiblich.

Der Select sähe ja dann z.B. so aus (Tabellen und Spaltennamen sind jetzt mal erfunden):

SELECT a.id, b.text
FROM tabelle a
JOIN geschlecht b ON (a.code = b.code)

Falls es nur die zwei Codes sind um die es geht und du dafür nicht extra eine Tabelle angelen.
Dann reicht z.B. die CASE Funktionalität. Also z.B. so:

SELECT a.id, CASE a.code WHEN 1001 THEN ‚männlich‘ WHEN 1002 THEN ‚weiblich‘ END
FROM tabelle a

Viele Grüße
Marco

Lieber Marco

Vielen Dank für deine Hilfe.

Eine solche Stammdatentabelle existiert auch tatsächlich, das Problem dabei ist leider, dass in einer Tabelle mehrere Spalten mit Codes sind, welche „übersetzt“ werden sollten. Es ist also leider nicht nur Geschlecht codiert in dieser Tabelle, sondern auch z.B. die Nationalität. Und alle diese Codes sind in einer einzigen Stammdatentabelle "gesammelt. Da ja die Zuweisung immer eindeutig sein soll nehme ich an, dass in einem solchen Fall nur die CASE Funktion bleibt?

(Sorry, bin wirklich blutige SQL-Anfängerin :wink: )

Vielen herzlichen Dank für deine Hilfe!

Liebe Toonia.

kein Problem, jeder fängt irgendwann mal an :wink:
Wenn es diese Stammdatentabelle gibt würde ich sie auch verwenden und nicht mit CASE arbeiten.

Der Nachteil am CASE wie zuletzt beschrieben ist, dass du damit die Texte fest im Select angeben würdest (z.B. den Text „männlich“ und den Text „weiblich“). Wenn sich jetzt aber mal der Text in der Stammdatentabelle ändert (z.B. in „Mann“ und „Frau“) müsstest du dein Select und evtl. auch viele andere Selects bei denen du auch so gearbeitet hast ebenfalls ändern.

Besser wäre es, du würdest du Stammdatentabelle mehrfach joinen. Mal ein theoretisches Beispiel mit Geschlecht, Anrede und Nationalität:

SELECT tab.id, ges.text, anr.text, nat.text
FROM tabelle tab
JOIN stammdaten ges ON (tab.code_geschlecht = ges.code)
JOIN stammdaten anr ON (tab.code_anrede = anr.code)
JOIN stammdaten nat ON (tab.code_nationalitaet = nat.code)

Wie du siehst gibt es hier die theoretische Tabelle „Tabelle“ der ich der Übersichtlichkeit halber das Kürzel „tab“ verpasst habe. Diese enthält die drei Spalten mit den verschiedenen Codes (code_geschlecht, code_anrede und code_nationalitaet).

Die Stammdatentabelle wird nun jeweils einmal mit jedem Code gejoined.
Jede bekommt ihr eigenes Kürzel (ges, anr und nat).
Mit dem Kürzel kann man nun bei den Spaltenangaben die entsprechenden Textspalten angeben.

Wichtig bei diesem Beispielselect wäre, dass die Codes auch immer gefüllt und nie NULL sind. Nehmen wir theoretisch mal an, es wäre doch möglich, dass die Nationalität nicht gefüllt sein muss, dann würde der Join für betroffene Datensätze nicht funktionieren. Stattdessen müsste man dann mit Outer Join arbeiten um die Datensätze ohne Nationalität ebenfalls anzuzeigen, also z.B. so:

SELECT tab.id, ges.text, anr.text, nat.text
FROM tabelle tab
JOIN stammdaten ges ON (tab.code_geschlecht = ges.code)
JOIN stammdaten anr ON (tab.code_anrede = anr.code)
LEFT OUTER JOIN stammdaten nat ON (tab.code_nationalitaet = nat.code)

Ändert mann nun in der Stammdatentabelle irgendeinen der Texte, dann müssen die Selects nicht angepasst werden. Die Texte werden ja aus der Tabelle ermittelt.

Hilft dir das weiter?
Viele Grüße
Marco

Hallo,

die bessere Möglichkeit wäre eine 2. Tabelle, der den Codes die auszugebenden Werte zugeordnet sind. Diese kann man dann über ein join ausgeben.

Sind es nur wenige Codes gehts auch mit Case. Hier ein Beispiel

SELECT Gendercode, Name =
CASE Gendercode
WHEN 1001 THEN ‚männlich‘
WHEN 1002 THEN ‚weiblich‘
ELSE ‚wer weiss??‘
END,
Name
FROM Tabelle
ORDER BY Name;
GO

Lieber Marco

Vielen herzlichen Dank!

Nach einigem Ausprobieren und Fluchen (was aber eher mit meinem Programm als mit SQL zu tun hatte :wink: ) hat es nun mit dieser Methode geklappt :wink:

Du hast mir viel Zeit und Arbeit erspart, vielen herzlichen Dank :smile:

Viele Grüsse
Toonia

Ojemine…Die ganze Abfrage ist nochmals komplizierter und es funktioniert irgendwie nicht mit diesem JOIN der Stammdatentabelle…vielleicht kannst Du mir weiterhelfen:

Es ist so: ich habe insgesamt 3 verschiedene Tabellen die ich verknüpfen muss. Von diesen 3 Tabellen benötige ich aber jeweils nicht alle Spalten. In allen dieser 3 Tabellen hat es Codes, welche ich dann wiederum mit der Stammdatentabelle verknüpfen müsste.
Meine Abfrage sah ungefähr so aus (abstrahier) (und hat nicht funktioniert):

SELECT T0.Geschlecht, T1.Nationalität, T1.Geburtsjahr, T2.Beruf, T3.Bezeichnung FROM tabPerson T0, tabPerson2 T1, tabBeruf T2
WHERE T0.id = T1.id and T1.idBeruf = T2.idBeruf
JOIN tabStammdaten T3 ON (T0.Geschlecht = T3.idGeschlecht)

Was mache ich falsch? Ich habe auch schon versucht, das WHERE hinter das JOIN zu verschieben, aber es funktioniert auch nicht.

Irgend eine Idee?

Vielen Dank im Voraus.

Viele Grüsse
Toonia

Noch eine Ergänzung: Die Abfrage sah korrekterweise so aus:

SELECT T0.idGeschlecht, T1.idNationalität, DATEPART(YEAR,T1.Geburtsdatum) AS Geburtsjahr, T2.idBeruf, T3.Bezeichnung AS Geschlecht, T4.Bezeichnung AS Nationalitaet, T5.Bezeichnung AS Beruf FROM tabPerson T0, tabPerson2 T1, tabBeruf T2
WHERE T0.id = T1.id and T1.idBeruf = T2.idBeruf
JOIN tabStammdaten T3 ON (T0.Geschlecht = T3.codeGeschlecht)
JOIN tabStammdaten T4 ON (T1.idNationalität = T4.codeNationalität)
usw.usf.

Die Fehlermeldung lautet übrigens "Inocorrect Syntax near „tabStammdaten“

Hi Toonia,

ich kann es jetzt leider nicht ausprobieren, aber evtl. liegt es daran, dass du verschiedene Join Syntax verwendest. Ich denke man sollte entweder mit JOIN oder mit WHERE und ‚=‘ arbeiten. Also entweder so:

SELECT T0.idGeschlecht, T1.idNationalität, DATEPART(YEAR,T1.Geburtsdatum) AS Geburtsjahr, T2.idBeruf, T3.Bezeichnung AS Geschlecht, T4.Bezeichnung AS Nationalitaet, T5.Bezeichnung AS Beruf
FROM tabPerson T0
JOIN tabPerson2 T1 ON (T0.id = T1.id)
JOIN tabBeruf T2 ON (T1.idBeruf = T2.idBeruf)
JOIN tabStammdaten T3 ON (T0.Geschlecht = T3.codeGeschlecht)
JOIN tabStammdaten T4 ON (T1.idNationalität = T4.codeNationalität)

Oder eben so:

SELECT T0.idGeschlecht, T1.idNationalität, DATEPART(YEAR,T1.Geburtsdatum) AS Geburtsjahr, T2.idBeruf, T3.Bezeichnung AS Geschlecht, T4.Bezeichnung AS Nationalitaet, T5.Bezeichnung AS Beruf
FROM tabPerson T0, tabPerson2 T1, tabBeruf T2, tabStammdaten T3, tabStammdaten T4
WHERE T0.id = T1.id
AND T1.idBeruf = T2.idBeruf
AND T0.Geschlecht = T3.codeGeschlecht
AND T1.idNationalität = T4.codeNationalität

Bei JOIN handelt es sich um die ANSI Syntax. Diese ist standardisiert sollte auf allen Datenbanken funktionieren. Welche Datenbank nutzt du eigentlich? Oracle, MySQL…?

Viele Grüße
Marco

Hallo Marco

vielen Dank für deine Antwort.

Es hat jetzt funktioniert, auch mit verschiedenen „Abfrageformen“. Ich denke es gab ein Problem das Datenbankbasiert ist (ich nutze übrigens MySQL): Die Datenbank wurde damals teilweise leider etwas unglücklich konstruiert so dass in zwei verschiedenen Tabelle eine Variable gleich benannt ist, so gibt eine Variable „idLand“ in zwei verschiedenen Tabellen (ist im Beispiel nicht erwähnt). Die Variable hat zwar unterschiedliche „Bedeutungen“ aber natürlich ist in den Stammdaten nur ein Code für „Land“ hinterlegt und beide Variablen „zeigen“ darauf. Das hat wohl die Probleme verursacht. Auch wenn ich die Tabellen-Aliasse davor gesetzt habe, hat die Unterscheidung wohl nicht richtig funktioniert. Als ich die Variable in der Abfrage der einen Tabelle rausgeschmissen habe, hat es jedenfalls funktioniert, bzw. eine weitere Variable, welche allerdings nicht doppelt vorkommt, konnte ebenfalls nicht zugeordnet werden. Dies hab ich dann halt mit CASE gelöst (hat nur zwei Bezeichnungen).

Für diese Abfrage ist zwar das Problem gelöst, nur befürchte ich, dass die zwei Tabellen, in welcher die „doppelte“ Variable idLand vorkommt, relativ häufig verknüpft werden müssen und da es bei Land fast 300 Bezeichnungen gibt, ist dies nicht so einfach mit CASE zu lösen…Siehst Du da eine Lösung oder müsste die Variable in der Datenbank umbenannt werden?

Viele Grüsse
Toonia

Hallo Toonia,

also das es doppelte Felder (du nennst es Variablen) gibt sollte eigentlich kein Problem darstellen. So kommt es ja auch in vielen Datenbanken vor, dass es in jeder Tabelle die Spalte bzw. das Feld „id“ gibt und das ist ja im Prinzip nichts anderes. Ich halte es auch nicht für schlecht konstruiert. Für solche Fälle gibt es eben die Tabellen-Aliasse, mit denen du es ja auch versucht hattest.
Ich denke der Fehler muss woanders gelegen haben.

Wie lautet denn genau die Fehlermeldung? bzw. kannst du mir das betroffene Select schicken?

Liebe Grüße
Marco

Hallo Toonia,

Deine gewählten Stichworte liefern Dir die Lösung.
Entweder verwendest Du einen case-Ausdruck in Deiner select-Anweisung
und musst alle zugeordneten Werte auflisten oder Du legst Dir eine
Übersetzungstabelle an, die die „integer-zu-String“-Beziehung aufnimmt
und ziehst diese Übersetzungstabelle in Deinem select entweder mit
einem left-join über die integer-Spalten hinzu oder verwendest
einen select-Ausdruck als Spalte.

Beispiele mit Übersetzungstabelle:
Tabelle mit referenzierter int-Spalte: „person“, int-Spalte „geschlecht“, String-Spalte „name“
Systemtabelle: „geschlechtuebersetzung“, int-Spalte „geschlecht“, String-Spalte „nameDeutsch“

SELECT p.name
, g.nameDeutsch AS geschlecht
FROM person p
LEFT JOIN geschlechtuebersetzung g ON g.geschlecht = p.geschlecht

SELECT p.name
, (SELECT g.nameDeutsch FROM geschlechtuebersetzung g WHERE g.geschlecht = p.geschlecht) AS geschlecht
FROM person p