Entwickler-Ecke
Datenbanken - [SQL] Mehrere Zeilen zusammenfassen
Der Jan - Fr 16.12.05 11:17
Titel: [SQL] Mehrere Zeilen zusammenfassen
Hallo,
ich hab ein Problem bei einer SQL Abfrage bzw. weiss ich gar nicht, ob das, was ich vorhabe einfach mit SQL geht:
Tabelle "Raten", enthält Daten zu monatlichen Ratenzahlungen bei bestimmten Verträgen:
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8: 9:
| CREATE TABLE RATEN ( RATEN_ID INTEGER NOT NULL, RATEN_NR INTEGER, RATEN_START_DAT D_DATUMNULL, RATEN_END_DAT D_DATUMNULL, RATEN_BETRAG D_ZAHL2KOMMANOTNULL, //monatliche Rate LEASING_VERTR_ID TINT, //Vertrags-ID RATEN_MONAT D_DATUMNULL ); |
Jetzt bräuchte ich eine Abfrage, mit der ich alle Raten eines Vertrages in eine Zeile bekomme.Allerdings nicht z.B. mittels SUM/GROUP, sondern jede Rate muß in eine Spalte.
Dafür habe ich eine Zieltabelle (RATEN2, wie sinnig :) )
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8:
| CREATE TABLE RATEN2 ( VERTR_ID INTEGER NOT NULL, RATE01 D_ZAHL2KOMMA, RATE02 D_ZAHL2KOMMA, //undsoweiter RATE71 D_ZAHL2KOMMA, RATE72 D_ZAHL2KOMMA ) |
Wie könnte man das machen?
Moderiert von
raziel: Code- durch SQL-Tags ersetzt
noidic - Fr 16.12.05 11:33
Ist die Anzahl der Raten festgelegt? Dann ginge das mit n ( n = Anzahl der Raten ) Joins...
Der Jan - Fr 16.12.05 11:35
Nein. Es sind zwischen 12 und 72.
Wie würde das mit den n Joins aussehen?
Der Jan - Fr 16.12.05 12:47
ich habe mir überlegt, ob man das vielleicht mit einer (oder zwei) Stored Procedure hinkriegen könnte. So sinngemäß: (Pseudocode)
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| PROCEDURE wasweissich FOR SELECT LEASING_VERTR_ID FROM RATEN INTO :act_ID DO FOR SELECT LEASING_VERTR_ID, RATEN_BETRAG, RATEN_NR FROM RATEN INTO :temp_ID, :temp_BETRAG WHERE LEASING_VERTR_ID = :act_ID ORDER BY RATEN_NR DO IF(erster_datensatz) INSERT INTO RATEN2 (VERTR_ID, RATE01) VALUES (:temp_ID, :temp_BETRAG) ELSE UPDATE RATEN2 SET RATE_xx = :temp_BETRAG //hier Problem WHERE :temp_ID = :act_ID
SUSPEND; END; |
Ginge das prinzipiell so?
Ein Problem: wie setze ich das "RATE_xx" im ELSE-Zweig? Kann man hier evtl. mit Arrays arbeiten?
Moderiert von
raziel: Code- durch SQL-Tags ersetzt
alzaimar - Fr 16.12.05 12:56
Du musst eine 'Pivot-Tabelle' bauen:
Wenn das hier der Inhalt der Tabelle ist
ID NR WERT
1 1 10
1 2 20
1 3 30
2 1 10
3 2 20
Und Du willst eine Tabelle haben wie die hier:
ID WERT1 WERT2 WERT3
1 10 20 30
2 10 NULL NULL
3 NULL 20 NULL
Dann schreibst Du einfach:
SQL-Anweisung
1: 2: 3: 4: 5: 6:
| select [ID], sum (case when Nr=1 then Wert Else NULL end) as Wert1, sum (case when Nr=2 then Wert Else NULL end) as Wert2, sum (case when Nr=3 then Wert Else NULL end) as Wert3 from Tabelle group by [ID] |
Wenn Dein SQL-Server das 'case' nicht versteht (MSSQL verstehts), dann geht es so:
SQL-Anweisung
1: 2: 3: 4: 5: 6:
| select [ID], (select Sum (Wert) from Tabelle x where x.Nr = 1 and x.[ID] = t.[ID]) as Wert1, (select Sum (Wert) from Tabelle x where x.Nr = 2 and x.[ID] = t.[ID]) as Wert2, (select Sum (Wert) from Tabelle x where x.Nr = 3 and x.[ID] = t.[ID]) as Wert3 from Tabelle t group by [ID] |
Summieren deshalb, weil es (unabhängig von Deinem konkreten Fall) sein kann, das zu einer Nr und einer ID mehrere Werte existieren.
Das Wort 'Pivot' kommt von 'Drehen', weil man immer einen Teil der Tabelle um 90 Grad dreht (Alle Werte einer ID stehen in der Tabelle untereinander, im Pivot dann nebeneinander).
Der Jan - Fr 16.12.05 15:25
Das hilft mir schonmal ein stückchen weiter. Allerdings isses bei mir nicht so direkt einsetzbar, da ich eine Spalte wie "NR" in deinem Beispiel nicht habe.
Vielmehr soll der entsprechende Wert aus der ersten passenden Zeile (mit der richtigen ID) in die erste Spalte, der zweite WErt in die zweite spalte usw.
alzaimar - Fr 16.12.05 16:18
Ah... ok, ich dachte, die RATEN_NR wäre das..
Dann ist das nicht trivial. Aber mit SQL geht das trotzdem. Weil aber Dein Darstellungswunsch sich nicht mit deinen Daten deckt (hast ja keinen individuellen Ratenzähler je Vertrags_ID) musst Du etwas mehr tun:
Es gibt Komponenten (
http://www.devexpress.com, QuantumGrid 5), die können Master-Detail Beziehungen so ähnlich darstellen, ohne das man viel rumhantieren muss. Die Master-Tabelle sind die Verträge, die Details sind die Raten. Die Verträge werden untereinander, die Raten jedes Vertrages unterhalb der 'Vertragszeile' einfach nebeneinander dargestellt.
Wenn Du das selbst basteln willst, würde ich die gesamte Tabelle in Delphi einlesen, und in einem geeigneten Grid, oder einer lokalen Tabelle (ADO mit Texttreiber und LockType=ltBatchOptimistic, dann ist es ein In-Memory-Dataset ;-) selbst generieren:
Sei 'T' die lokale Tabelle
Quelltext
1: 2: 3: 4:
| ForEach Record r do T.Locate ('Vertrag_ID',r.ID,[]); F := FindNullRatenField (T); F.AsInteger := R.Rate |
Für jede Zeile in der Raten-Tabelle suchst Du die Zeile mit dem Vertrag (oder erzeugst eine neue, per append). Dann suchst Du in dem Record das erste RatenXX-Feld, das noch nicht befüllt ist und packst da den Wert rein.
Natürlich kannst Du das auch in SQL-Coden. Aber nur, wenn Du den Server ärgern willst.
Der Jan - Di 20.12.05 11:33
Danke für die Hilfe.
Ich glaube, ich will den Server ärgern :P
Nee, mal im Ernst... Ich kann hier mit Delphi nicht wirklich ran, drum muß es in SQL sein, aber nun krieg ich es hin. :dance:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!