joni2000de
Goto Top

SQL Datensatzzeilen als Spalten anordnen

Hi Admins,

ich habe da wieder mal ne Frage (DB = Oracle). Wie kann ich die Datensätze einer Tabelle in Spalten einer Abfrage anordnen?

Tabelle Kunden
NR NAME
01 Hans
02 Rudi

Tabelle Kontakt
KNR KONTAKTART EINTRAG
01  Handy      123456789
01  Festnetz   23456789
02  Mail       123@456.de
01  Mail       789@456.de
02  Handy      987654321

Mein Wunschergebnis
NR NAME HANDY     FESTNETZ MAIL
01 Hans 123456789 23456789 789@456.de
02 Rudi 987654321          123@456.de

Die Spaltenüberschriften sollten aus der Tabelle Kontakt übernommen werden. Es sollten so viele Spalten "erzeugt" werden wie es unterschiedliche Einträge in Kontaktart gibt.

Ich bin da noch relativ neu auf dem Gebiet und hoffe auf den richtigen Tip. Danke

Gruß Joni

Content-ID: 157202

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

Ausgedruckt am: 25.11.2024 um 21:11 Uhr

nxclass
nxclass 17.12.2010 um 20:09:23 Uhr
Goto Top
Pivot- oder Kreuz- Tabellen gibt es nicht im normalen SQL.

entweder Du kannst die Tabellen in Normalform umwandeln oder Du versuchst sowas:
SELECT
  k.*,
  h.EINTRAG,
  f.EINTRAG,
  m.EINTRAG
FROM
    Kunden k
        LEFT JOIN Kontakt h ON (k.NR = h.KNR AND h.KONTAKTART = 'Handy')  
        LEFT JOIN Kontakt f ON (k.NR = f.KNR AND f.KONTAKTART = 'Festnetz')  
        LEFT JOIN Kontakt m ON (k.NR = m.KNR AND m.KONTAKTART = 'Mail')  
;
joni2000de
joni2000de 20.12.2010 um 08:52:09 Uhr
Goto Top
Hi nxclass,

d. h. wenn ich keinen Einfluss auf die Tabelle habe und ich das richtig verstanden habe muss ich in einer Abfrage vorab die Inhalte von Kontaktart ermitteln (die ich ja nicht kenne) und anschließend eine 2. Abfrage bauen (aufbauend auf den Inhalten der 1. Abfrage) die dann ungefähr so wie deine obige aussieht. Das muss dann immer außerhalb von SQL gelöst werden (z. B. VBS)?

Gruß Joni
Biber
Biber 20.12.2010 um 10:05:54 Uhr
Goto Top
Moin joni2000de,

ich will nochmal ganz ausdrücklich die Aussage von nxclass unterstützen: Bring die Tabellen in eine brauchbare (Normal-)Form..

So wie von dir skizziert ist das nicht brauchbar... nicht für Ad-hoc-Abfragen und Auswertungen geeignet.

Da hat sich irgendein Datenbank-Grundlagen-für-Geographielehrer-VHS-Kurs-Absolvent am Datenmodellieren versucht.

Die implizite Unterstellung, in der Tabelle "Kontakt" werden Entitäten namens "Eintrag" gesammelt und ein "Eintrag" kann vom Typ "Handy", "Mail" oder "Handy" sein...

Dönekens.

Eine Handy-Nummer ist eine Handynummer. Mit definitiv anderen Eigenschaften (oder auch Gültigkeitskriterien) als eine Mailadresse oder eine Festnetznummer.
Hier ist es an der falschen Stelle "strukturiert". Schau dir beispielsweise die "Kontaktdaten"-Felder in einem M$-Outlook an.
Da stehen Telefon dienstl/Telefon privat/Fax/Email dienstlich/Email privat etc als einzelne Felder nebeneinander.
Niemand würde dort eine Liste mit "Eintrag 1" bis "Eintrag 17" erwarten, bei der nach Eingabe die Auswahl "Festnetz"/"Handy"/"Mailadresse" abgefordert wird.

Wenn du mit der Struktur oben weitermachst, dann musst du die Felder wieder mit mehr oder weniger Aufwand als einzeln benennbare Spalten umgruppieren.

Das geht
  • mit PL/SQL --> Oracle-Serverseitig -> das einzig Akzeptable performanzmäßig
  • ab Oracle 11g auch mit dem Schlüsselwort PIVOT (siehe Anmerkungen unten)
  • oder THEORETISCH auch mit irgendeinem anderen Skript/Progrämmle (meinetwegen auch VBS). Ob ich nun ausgerechnet für eine Oracle-DB ein paar ADODB-RecordSets zusammenlügen will... ist Geschmackssache. Falls ihr keinen [Oracle-]DBA in der Firma habt, dann könntest du es evtl unbemerkt machen. Ist so ähnlich wie mit selbstzusammengebrezelten Monster-Trucks... wenn du die nur im eigenen Garten fährst oder besser noch im eigenen Keller, dann wird keiner was dagegen sagen.

Nichtsdestotrotz -> was du richtig erkannt hast: Du musst IMMER die aktuelle [DISTINCT] Anzahl unterschiedlicher Werte in "Einträge" ermitteln,
also die Anzahl der Pivot-"Spalten".
Das gilt auch bei die Nutzung der Oracle 11g-PIVOT-SQL-Syntax.
Und die Anmerkung dazu: das im normalen SQl nutzbare Schlüsselwort PIVOT erleichtert zwar vieles, aber:
Bedauerlicherweise müssen davor und dahinter auch noch ein paar andere Angaben stehen.
Diese Syntax ist ein bisschen ruppig, schau dir bitte mal ein, zwei Suchmaschinen-Fundstellen zu "Oracle pivot" an.

Meine Empfehlung:
  • Lass die Tabelle "Kontakt" ummodellieren. Einzig schmerz- & stressfreier Rat. Alles andere bedeutet jahrelangen Anpassungsaufwand und Resourcenverbrennerei.
  • Wenn das nicht gehen sollte vermeintlich, weil das 2 Manntage Aufwand bedeuten würde laut Dienstleister, dann lass von einem Oraclefuzzy einen VIEW auf die Kontakttabelle anlegen. Mit Pivotierung der heute real vorhandenen "Eintragsarten". Wenn es heute 5 "Arten" sind, dann hat der VIEW 5 Spalten dafür, wenn es im nächsten Juni 12 Werte sind, dann muss der View eben angepasst werden.

Grüße
Biber
nxclass
nxclass 20.12.2010 um 10:14:53 Uhr
Goto Top
die Inhalte von Kontaktart ermitteln
anschließend eine 2. Abfrage bauen
... - ja - die 'Kontakt.KONTAKTART' müsste dann natürlich in irgend einer weise bekannt sein:
SELECT KONTAKTART
FROM Kontakt
GROUP BY KONTAKTART;

ich keinen Einfluss auf die Tabelle habe
... und evtl. sogar mehrere E-Mail Adressen pro Benutzer gespeichert sind, würde es evtl. Sinn machen:
SELECT
  ku.*,
  GROUP_CONCAT( ku.KONTAKTART ) AS 'list_KONTAKTART',  
  GROUP_CONCAT( ku.EINTRAG ) AS 'list_EINTRAG'  
FROM
    Kunden ku
        LEFT JOIN Kontakt ko ON (ku.NR = ko.KNR)
GROUP BY
  ku.NR
;
die Kontakt Einträge als Liste zurück zu geben. (GROUP_CONCAT() ist eine MySQL Funktion - aber ich denke bei deiner DB gibt es auch sowas)
joni2000de
joni2000de 20.12.2010 um 12:14:14 Uhr
Goto Top
Edit
Hat sich erledigt, das Problem liegt woanders (siehe unten).

Hi ihr beiden,

sehe schon, da hab ich wieder was ausgegraben. Dass das Datenbankmodell nicht so toll ist war mir klar. Naja ich weiß nicht wie lange wir noch damit arbeiten, darum möchte ich da nicht zu viel investieren. Erst einmal danke für die Aufklärung.

Da ist noch eine andere Frage aufgetaucht. Wenn mir mal beim obigen Beispiel bleiben. Wenn in der Tabelle Kontakt die Spalte Kontaktart nicht die Kontaktart selber sondern eine Nummer enthalten würde (z. B. Handy = 1, Festnetz = 2, Mail = 3) und es zusätzlich eine Tabelle Kontaktart mit den entsprechenden Einträgen geben würde, wie müsste dann die Abfrage aussehen? Gehen wir davon aus, dass jeder Kunde entweder eine oder keine Kontaktart hinterlegt hat und wir die "Aufteilung" nicht brauchen.

Das wäre dann ja ein zusätzliches join (JOIN Kontaktart KA ON KA.NR = KO.Kontaktart) im left join (LEFT JOIN Kontakt KO on KU.NR = KO.KNR). Wie kriege ich das zusammen?

Nochmal danke für eure Hilfe.

Gruß Joni
joni2000de
joni2000de 20.12.2010 um 14:12:02 Uhr
Goto Top
Da bin ich nochmal.

case
   when SO.NR=700 then 'ja'  
   when SO.NR<>700 then 'doppelt'  
   else null
end as EZ

Kann ich bei obigem Select das Where/Having so gestalten, das ich nur die Zeilen ungleich doppelt kriege (=> null und ja)?
EZ <> 'doppelt' liefert ungültiger Bezeichner

Danke
Gruß Joni