PDA

Vollständige Version anzeigen : Daten der Tabelle "komprimieren"


Gustav0815
26.10.2011, 20:27
Hallo,

ich habe eine Tabelle in der die Daten wie folgt vorliegen (Bespielhaft).

date a1 a2 b1 b2
15.01.2011 5
15.01.2011 6
15.01.2011
16.01.2011 7 5
16.01.2011 3
15.01.2011
17.01.2011

Ich möchte nun die Daten derart mit einer Abfrage "komprimieren", das die Daten danach wie folgt aussehen.

date a1 a2 b1 b2
15.01.2011 5 6
16.01.2011 7 5 3
17.01.2011

Wie müsste ich da vorgehen??

achtelpetit
26.10.2011, 22:15
Das Stichwort heißt transponieren. Such hier mal nach "SQL-Liste".

Gustav0815
27.10.2011, 07:06
Habe die Tabellen noch einmal eingebaut, da dies leider nicht so geklappt hat. Editieren war leider auch nicht möglich.

Isttabelle


date a1 b1 a2 b2
15.01.2011 5
15.01.2011 6
15.01.2011
16.01.2011 7 5
16.01.2011 3
17.01.2011


Soll-Abfrage:

date a1 b1 a2 b2
15.01.2011 5 6
16.01.2011 7 5 3
17.01.2011

Ist das wirklich schon transponieren? Ich tausche Zeilen und Spalten garnicht, aber ich schau es mir mal an. Danke für den Tipp.

Atrus2711
27.10.2011, 08:29
Hi,

das ist kein Transponieren. SQLLISte sollte gehen, aber es geht auch ohne VBA:

Baue manuell eine Hilfstabelle auf mit folgenden Feldern: Stichtag (Datum/Zeit), Größe (Text), Wert (Zahl)
Lass über 4 Anfügeabfragen (je eine für a1, a2, b1, b2) die nichtleeren Daten der einzelnen Spalte in die Hilfstabelle ausgeben. Diese Hilfstabelle hat am Ende dann so viele Zeilen, wie deine Urtabelle "Zellwerte" hat (im Beispiel also 5).
Nimm diese Hilfstabelle als Basis für eine Kreuztabellenabfrage mit Stichtag = Zeile, Größe = Spalte und Summe(Wert) als Wert
Diese Kreuztabelle kann ggf. auch als Basis weiterer Abfragen dienen.


PS: Spalten mit "laufenden Nummern" im Namen (Mehrfachspalten) sind denormalisiert. Das scheint dir gerade auf die Füße zu fallen.

Gustav0815
27.10.2011, 09:06
Habe das Problem inzwischen lösen können nachdem ich im Netz etwas ähnliches gefunden habe.

Für jede Spalte (a1 - b2) wird eine Funktion benötigt, die wie folgt aussehen:


Public Function SZ1(datea As Long) As String
Dim strSQL As String
Dim rs As DAO.Recordset

strSQL = "SELECT a1 FROM tabelle1 WHERE datea =" & datea

Set rs = DBEngine(0)(0).OpenRecordset(strSQL)

Do While rs.EOF = False
If Not IsNull(rs!a1) Then SZ1 = rs!a1
rs.MoveNext
Loop

rs.Close
Set rs = Nothing
End Function

Public Function SZ2(datea As Long) As String
Dim strSQL As String
Dim rs As DAO.Recordset

strSQL = "SELECT b1 FROM tabelle1 WHERE datea =" & datea

Set rs = DBEngine(0)(0).OpenRecordset(strSQL)

Do While rs.EOF = False
If Not IsNull(rs!b1) Then SZ2 = rs!b1
rs.MoveNext
Loop

rs.Close
Set rs = Nothing
End Function


Public Function SZ3(datea As Long) As String
Dim strSQL As String
Dim rs As DAO.Recordset

strSQL = "SELECT a2 FROM tabelle1 WHERE datea =" & datea

Set rs = DBEngine(0)(0).OpenRecordset(strSQL)

Do While rs.EOF = False

If Not IsNull(rs!a2) Then SZ3 = rs!a2
rs.MoveNext
Loop

rs.Close
Set rs = Nothing
End Function
Public Function SZ4(datea As Long) As String
Dim strSQL As String
Dim rs As DAO.Recordset

strSQL = "SELECT b2 FROM tabelle1 WHERE datea =" & datea

Set rs = DBEngine(0)(0).OpenRecordset(strSQL)

Do While rs.EOF = False
If Not IsNull(rs!b2) Then SZ4 = rs!b2
rs.MoveNext
Loop

rs.Close
Set rs = Nothing
End Function


Dann wird nur noch eine kleine Abfrage benötigt, die das ganze ausführt.


SELECT datea, SZ1([datea]) AS A1, SZ2([datea]) AS A2, SZ3([datea]) AS A3, SZ4([datea]) AS A4
FROM tabelle1
GROUP BY datea;


Date habe ich in datea geändert.

Nach Aufruf der Abfrage erfolgt die Ausgabe wie gewünscht.

zra8886
27.10.2011, 09:28
Mein Lösungsvorschlag:
auch wenn bereits eine Lösung da ist, aber meine Arbeit sollte nicht umsonst sein.

abfr_Datenkompression_A1
SELECT tbl_Datenkompression.ID, tbl_Datenkompression.Tagesdatum, tbl_Datenkompression.A1, "A1" AS Beschreibung
FROM tbl_Datenkompression
WHERE (((tbl_Datenkompression.A1) Is Not Null));

abfr_Datenkompression_A2
SELECT tbl_Datenkompression.ID, tbl_Datenkompression.Tagesdatum, tbl_Datenkompression.A2, "A2" AS Beschreibung
FROM tbl_Datenkompression
WHERE (((tbl_Datenkompression.A2) Is Not Null));

abfr_Datenkompression_B1
SELECT tbl_Datenkompression.ID, tbl_Datenkompression.Tagesdatum, tbl_Datenkompression.B1, "B1" AS Beschreibung
FROM tbl_Datenkompression
WHERE (((tbl_Datenkompression.B1) Is Not Null));

abfr_Datenkompression_B2SELECT tbl_Datenkompression.ID, tbl_Datenkompression.Tagesdatum, tbl_Datenkompression.B2, "B2" AS Beschreibung
FROM tbl_Datenkompression
WHERE (((tbl_Datenkompression.B2) Is Not Null));


Zusammenführen mit:
abfr_union_Datenkompression
SELECT * from abfr_Datenkompression_A1
Union
SELECT * from abfr_Datenkompression_A2
UNION
SELECT * from abfr_Datenkompression_B1
UNION
SELECT * from abfr_Datenkompression_B2;

und dann die Übersicht mit der abfr_union_Datenkompression_Kreuztabelle
TRANSFORM Sum(abfr_union_Datenkompression.A1) AS SummevonA1
SELECT abfr_union_Datenkompression.Tagesdatum
FROM abfr_union_Datenkompression
GROUP BY abfr_union_Datenkompression.Tagesdatum
PIVOT abfr_union_Datenkompression.Beschreibung;


Vielleicht etwas umständlich, aber das gewünschte Ergebnis wird geliefert.
mfg
Roland

Gustav0815
27.10.2011, 11:28
Danke für Deine Mühe.

Eine reine Lösung über Abfragen würde ich bevorzugen, da mein Ergebnis zwar tadellos funktioniert, aber die Laufzeit nicht unerheblich ist. In der hier geposteten Beispieltabelle läuft es noch sehr schnell, aber leider ist es ja nur ein Beispiel. Im realen handelt es sich aber um eine Abfrage die entscheidend mehr Datensätze liefert.
Da die Funktion 4 x (Anzahl der DS) oft aufgerufen wird, läuft es selbst bei 40 DS schon kritisch. Werde mal sehen, ob ich mit temporären Tabellen arbeiten kann.

Deine Lösung habe ich natürlich auch probiert, aber es hat leider 2 "Fehler".
1. DS in den ein Datum aber keine Daten in A1-B2 vorhanden sind (17.01.2011) werden nicht berücksichtigt. Sie sollen aber im Ergebnis vorhanden sein.
2. In der Kreuztabelle die Summe bilden funktioniert nicht, da es sich um Strings handelt.

Im Grunde ist das Problem aber gelöst.

Atrus2711
27.10.2011, 11:54
Hi,

1. DS in den ein Datum aber keine Daten in A1-B2 vorhanden sind (17.01.2011) werden nicht berücksichtigt. Sie sollen aber im Ergebnis vorhanden sein.
Wenn du die als Fehlanzeige nutzen willst, könnte es nützlich sein, die leeren Sätze doch nicht auszuschließen (d.h. das Kriterium WHERE A1 IS Null weg!) und die dann entstehenden leeren Werte mit NZ(A1,0) in Nullen o.ä. zu wandeln.

2. In der Kreuztabelle die Summe bilden funktioniert nicht, da es sich um Strings handelt
5, 6 und 7 sieht zumindest nach Werten aus, die man mit Konvertierungen in Zahlen wandeln könnte. Das geht auch in der Kreuztabelle (Cdbl(A1) summieren lassen). Wenn es wirklich Strings sein sollten, musst du dich entscheiden, was mit den - ggf mehreren - Strings geschehen soll, die in einer Zelle zu liegen kommen. In einer Zelle kann es halt nur einen Wert geben.

ebs17
27.10.2011, 13:00
@Gustav0815: Man kann doch davon ausgehen, dass es für jedes Datum nur genau einen Wert für Feld A1 (analog A2, B1, B2) gibt?
Dann würde ich einfach gruppieren:
SELECT
T.date,
Max(T.A1) AS A1,
Max(T.A2) AS A2,
Max(T.B1) AS B1,
Max(T.B2) AS B2
FROM Tabelle T
GROUP BY T.date

ebs17
27.10.2011, 16:08
Als Nachtrag: Wenn man diese fünf Felder indiziert, sollte das hinsichtlich Performance wohltuend auswirken, zusätzlich zur Einfachheit der Abfrage.