PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Datensätze - aus Zeilen spalten machen



Bubble
26-02-2004, 12:56
Hallo,

ich stehe vor folgendem Problem:

Ich habe eine Tabelle, sagen wir mal

Vorname Name
====== =====
Heinz Müller
Hans Maier


Nun möchte ich auf diese Tabelle eine Abfrage machen, damit folgendes Ergebnis herauskommt:

Vorname1 Name1 Vorname2 Name2
======= ====== ======= =====
Heinz Müller Hans Maier

Zu lösen wäre dies m.E. nach über Sub-Selects, bspw. beginnt das so:

SELECT (SELECT TOP 1 Vorname FROM ...) AS Vorname1,
(SELECT TOP 1 Name FROM ...) AS Name1,
???

Nur jetzt hörts leider auf :-(. Auf den ersten Datensatz über TOP 1 zuzugreifen ist kein Problem, nur wie komm ich auf den 2. (und einen 3., 4., 5. usw).

Möglich wäre es in diesem (vereinfachten) Fall in die Tabelle eine laufende Nummer einzufügen und auf die zu gehen, nur in meinem (komplizierteren) Fall ist das leider nicht möglich! Gibts ne andere Möglichkeit?
Vielen Dank schonmal im Voraus,
Bubble

Martin Ament
26-02-2004, 15:02
Musst Du das in reinem SQL erledigen, und wenn, was ist die DB-Engine, oder verwendest du das innerhalb einer prozeduralen Sprache ?

Christoph
26-02-2004, 15:09
In reinem SQL geht das glaube ich nicht. Allerdings kann ich das jetzt auf die Schnelle nicht beweisen.

Da wirst Du wohl mit einer prozeduralen Sprache arbeiten müssen. Damit ist es dann aber ein Kinderspiel: einfach jede Zeile fetchen und in einem String aneinanderhängen.

Bubble
26-02-2004, 15:21
Nein es muss in reinem SQL sein (ich will damit eine View erstellen). Die Engine ist ein MS SQL Server 2000 und deren SQL-Variante TSQL.

Ich hab ja geschrieben, durchnummiert werden kann nicht. Ich habe das Problem jetzt mal so gelöst:

Ich habe eine Stored Procedure geschrieben, welche die Tabelleneinträge aus den Originaltabellen ausliest und durchnummerierte Hilfstabellen anlegt (einfach 1, 2, 3 usw. geht nicht, stellt euch das so vor dass beim obigen Beispiel die Einträge nach Geschlechter getrennt sind und bei jedem Geschlecht die Zählung wieder von 1 beginnen muss, nur hab ich nicht nur 2 versch. Kategorieren sondern einige tausend, was prinzipiell aber keinen Unterschied macht).

Die Hilfstabellen sind soweit vorhanden, müssen aber mind. 2 mal am Tag aktualisiert werden, da sich auch der Inhalt der Originaltabellen ändert. Finde ich daher keine schöne Lösung, auch wenn die Stored Procedures natürlich automatisiert ablaufen können. Nun denke ich ist es nicht mehr schwer auf Grundlage dieser Tabellen die View zu generieren.

Gibts vielleicht ne schönere Lösung? Stören tut mich halt vor allem der Punkt, dass die 'Hilfstabellen', auf denen die View basiert, nicht in Echtzeit mit den Orginaltabellen abgeglichen wird - und die auf dieser View basierte Auswertung evtl. veraltete Daten zeigt. Aber ich kann die View nicht auf den Originaltabellen erstellen, da diese nicht durchnummeriert sind ...

Hat jemand einen besseren Lösungsvorschlag?
Bubble

Christoph
29-02-2004, 17:00
Wenn ich Dich recht verstehe, dann willst Du das Ergebnis eines Selects transponieren (wenn man das Ergebnis als Matrix auffasst). Eine stored Procedure TRANSPOSE() müsste möglich sein, wenn Dein DBS Prozeduren unterstützt, die Mengen als Input und als Output akzeptieren. Ich glaube bei PostgreSQL ist sowas seit Version 7.3 möglich.

Allerdings musst Du ggf. aufpassen, denn relationale Datenbanken arbeiten nicht mit Tabellen/Matrizen, sondern mit Bags (= ungeordnete Listen von Tupeln).

Bubble
01-03-2004, 10:35
OK, es soll aber keine Stored Procedure, sondern eine View sein. Geht das trotzdem?
Bubble

Christoph
01-03-2004, 16:10
Original geschrieben von Bubble
es soll aber keine Stored Procedure, sondern eine View sein. Geht das trotzdem?

Wie schon mehrfach betont, geht das nicht mit reinem SQL. Allerdings kannst Du natürlich in der View-Definition eine stored Procedure aufrufen. In PostgreSQL z.B. ginge das so:

CREATE VIEW myview AS SELECT myproc();

Bei anderen DBS'en sollte ähnliches möglich sein.

Bubble
01-03-2004, 17:04
Ok, ich werde das morgen mal testen. Für heute mach ich Feierabend :p
Vielen Dank für deine Hilfe Christoph.
Bubble

Bubble
01-03-2004, 17:23
Also das war noch nichts mit dem Feierabend ...

Aber na gut. Ich verwende den MS SQL Server 2000 Enterprise Edition. Nun ist es so dass ich mal probeweise eine Funktion geschrieben habe, die mehrere Werte zurückgibt. Also nehmen wir mal mein Beispiel aus dem ersten Posting, die Funktion heißt Test und geht so:



CREATE FUNCTION Test RETURNS VARCHAR(255) AS
BEGIN
RETURN (SELECT Vorname FROM ...)
END


Also eine Funktion die sämtliche Vornamen zurückgibt.

Wenn ich nun eine View folgendermaßen erstelle:



CREATE VIEW myview AS SELECT Test() AS 'Vornamen'


Die View lässt sich erstellen, jedoch bekomme ich beim Versuch darauf zuzugreifen folgenden Fehler:

Subquery returned more than 1 value. This is not permitted when the subquery follows [ein paar Zeichen] or when the subquery is used as an expression.

Mir ist die Struktur noch nicht ganz klar, wie eine Funktion / eine Stored Procedure auszusehen hat, um Daten an eine View zurückzuliefern, und wie die View auszusehen hat, um diese Daten anzuzeigen. Ich werd mich morgen mal evtl. auf die Suche nach Doku oder Beispielen machen, aber wenn du was parat hättest wäre das super.
Nochmals vielen Dank.
Bubble

Christoph
01-03-2004, 18:57
Ich vermute mal, dass Du "SELECT * FROM (TEST()) x" schreiben musst (das letzte x braucht man bei PostgreSQL um einer ad hoc aus einem Subselect generierten Tabelle einen Namen zu geben, bei MSSQL kann es sein, dass man es auch weglassen kann).

Zum Transponieren wirst Du natürlich eine prozedurale Sprache im Funktionsrumpf brauchen, ich weiß nicht was MSSQL da verwendet (PL/SQL, PSM, Python, -?-).

Bubble
02-03-2004, 08:40
Nein, leider auch nicht.

MSSQL verwendet TSQL. Muss mal durch die Doku gehen ob es da ein äquivalentes Konstrukt gibt, die Prio ist allerdings nicht mehr allzu hoch, da es wie gesagt auf anderem Wege ja geht ... sollte sich noch was ergeben melde ich mich aber wieder.
Bubble