Autor Beitrag
Der Jan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98

Win2k prof, WinXP prof, Linux
D6 Prof, BCB4 Std, BCB6 Ent, BDS 2006 Ent
BeitragVerfasst: Fr 16.12.05 11:17 
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:

ausblenden 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 :) )
ausblenden 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 user profile iconraziel: Code- durch SQL-Tags ersetzt

_________________
Gruß, Jan
noidic
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 851

Win 2000 Win XP Vista
D7 Ent, SharpDevelop 2.2
BeitragVerfasst: Fr 16.12.05 11:33 
Ist die Anzahl der Raten festgelegt? Dann ginge das mit n ( n = Anzahl der Raten ) Joins...

_________________
Bravery calls my name in the sound of the wind in the night...
Der Jan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98

Win2k prof, WinXP prof, Linux
D6 Prof, BCB4 Std, BCB6 Ent, BDS 2006 Ent
BeitragVerfasst: Fr 16.12.05 11:35 
Nein. Es sind zwischen 12 und 72.
Wie würde das mit den n Joins aussehen?

_________________
Gruß, Jan
Der Jan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98

Win2k prof, WinXP prof, Linux
D6 Prof, BCB4 Std, BCB6 Ent, BDS 2006 Ent
BeitragVerfasst: 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)

ausblenden 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 user profile iconraziel: Code- durch SQL-Tags ersetzt

_________________
Gruß, Jan
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: 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:
ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
select   [ID],
  sum (case when Nr=1 then Wert Else NULL endas Wert1,
  sum (case when Nr=2 then Wert Else NULL endas Wert2,
  sum (case when Nr=3 then Wert Else NULL endas Wert3
from Tabelle 
group by [ID]

Wenn Dein SQL-Server das 'case' nicht versteht (MSSQL verstehts), dann geht es so:
ausblenden 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).

_________________
Na denn, dann. Bis dann, denn.
Der Jan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98

Win2k prof, WinXP prof, Linux
D6 Prof, BCB4 Std, BCB6 Ent, BDS 2006 Ent
BeitragVerfasst: 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.

_________________
Gruß, Jan
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: 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 (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
ausblenden 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.

_________________
Na denn, dann. Bis dann, denn.
Der Jan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98

Win2k prof, WinXP prof, Linux
D6 Prof, BCB4 Std, BCB6 Ent, BDS 2006 Ent
BeitragVerfasst: 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:

_________________
Gruß, Jan