Announcement

Collapse
No announcement yet.

Tabelle um 90 grad drehen (Pivot)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Tabelle um 90 grad drehen (Pivot)

    Hallo Zusammen,

    ich muss eine Tabelle um 90 Grad drehen, hier ein Beispiel:

    Code:
    NAME | WERT
    ------------------
    Name1|Wert1
    Name2|Wert2
    Name3|Wert3
    Name4|Wert4
    soll das werden:
    Code:
    Name1  |  Name2  |  Name3 |  Name4
    -------------------------------------------
    Wert1  | Wert2   | Wert3  | Wert4
    eine Möglichkeit, die ich kenne ist diese:

    Code:
    SELECT
    MAX(CASE NAME WHEN 'Name1' THEN WERT ELSE null END) as Name1,
    MAX(CASE NAME WHEN 'Name2' THEN WERT ELSE null END) as Name2,
    MAX(CASE NAME WHEN 'Name3' THEN WERT ELSE null END) as Name3
    MAX(CASE NAME WHEN 'Name4' THEN WERT ELSE null END) as Name4
    FROM TABLENAME
    Das Problem hierbei ist, dass ich die Werte in der Spalte "Name" explizit mit CASE abfragen muss. Allerdings habe ich eine Tabelle, bei der die Namen sich immer wieder ändern und ich deshalb diese CASE Anweisungen nicht benutzen kann.
    Hat jemand eine Idee, wie ich das machen kann? Mit ist jede Möglichkeit recht, auch proprietäre Firebird-Befehle, Stored Procedures usw.

    Gruß
    Horsti

  • #2
    Man könnte versuchen die Abfrage dynamisch anhand der Metadaten der Tabelle zu erzeugen

    Comment


    • #3
      Hast du da ein Beispiel?

      Anhand der Metadaten kann ich aber doch nur sehen, wie die Spalten heißen oder wielchen Datentyp sie haben usw. Wie kann ich das für meine Abfrage nutzen

      Comment


      • #4
        Hallo Horsti,

        eigentlich hast Du Deine Frage schon selbst beantwortet:

        Resultat soll ein generiertes Select sein:
        Zitat:
        "...
        SELECT
        MAX(CASE NAME WHEN 'Name1' THEN WERT ELSE null END) as Name1,
        MAX(CASE NAME WHEN 'Name2' THEN WERT ELSE null END) as Name2,
        MAX(CASE NAME WHEN 'Name3' THEN WERT ELSE null END) as Name3
        MAX(CASE NAME WHEN 'Name4' THEN WERT ELSE null END) as Name4
        FROM TABLENAME
        ..."

        Demnach machst Du eine Stored Procedure (SP1) mit Input "Tabellenname"und Ausgabe "SQL_SELECT als varchar(5000)" und "RESPONSE_HEDER als varchar(5000)". Da Du die Rückgabespalten nicht kennst, musst du sie vielleicht als mit einem Zeichen wie z.B. "|" separierte Zeichenkette zurückgeben, um weitere Verarbeitungen der Ergebnisse des generierten Select's machen zu können.

        Die SP1 erzeugt demnach die Anfrage an den übergebenen Tabellennamen und man erhält die Ergebnisse "Name1" u.s.w. Nöglicherweise muss man noch die Spaltennamen der Tabelle als Eingaben angeben. Jetzt stellst man sich die Zeile "MAX(CASE <NAME> WHEN '<ZeilenErgebnis-Name1>' THEN <WERT> ELSE null END) as <ZeilenErgebnis-Name1>," zusammen und fügt sie nach und nach zu einer Zeichenkette zusammen. Zum Schluss ergänzt man noch das Drumherum, also "Select <hat man jetzt bereits> from + tabellenname ". Diesen String kann man als Ergebnis der Prozedur zurückliefern. Mit einer weiteren DB-Anfrage sendet man den generierten Select als Anfrage an die DB und erhält das gewünschte Resultat zurück.

        Eine "stored procedure" zu schreiben ist relativ einfach und in der Firebird Hilfe sehr gut beschrieben. Programme wie "FlameRobin" geben auch eine Shell vor.

        Ich wünsche Erfolg beim Programmieren.

        Gruß...

        Comment


        • #5
          Das habe ich mir auch schon überlegt, allerdings wird es da ein Problem geben. Nämlich das "implementation limit". Die Abfrage kann so lang werden, dass Firebird damit nicht mehr klar kommt. Ich hab das schonmal "simuliert", indem ich eine Query per Hand erstellt habe, die so ca. 800 Variablen abfragt. Dann kommt ich an die Grenzen. Ich weiß auch noch nicht, wieviele Spalten eine Tabelle überhaupt haben kann. 800 oder mehr sind ja normalerweise eher unüblich .
          Ich probiers mal aus, mal sehen ob es klappt.
          Danke!

          Comment


          • #6
            Hallo,

            in solchen Fällen würde ich lieber eine das "normale" Abfrageergebnis der Tabelle in einer speziellen Klasse halten, dort in einem Vector oder einer Map speichern oder einer Liste mit eigener Struktur. Die Klasse kann man über Methoden abfragen, z.B. First, Next oder über Operator "[]" wie ein Array. Die Klasse verhält sich dann so wie ein zweidimensionales Array, wobei jede Zelle eine Struktur mit Daten besitzt.

            Ich vermute das wird bei den geschilderten Problemen die bessere und universellere Lösung sein. Denn falls die Tabelle zu lang wird, hätte ein Designproblem, da die Funktionsweise darunter leiden würde.


            Grüße...

            Comment


            • #7
              Oder man holt dynamisch den relevanten Bereich.
              800 und mehr Spalten kann man sowieso nicht auf einmal anzeigen.

              Comment

              Working...
              X