Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

SQL-Statement zur Konsolidierung zweier Tabellen

Begonnen von C4RL0, Januar 22, 2014, 14:03:39

⏪ vorheriges - nächstes ⏩

C4RL0

Hallo zusammen,
ich benötige Hilfe bei einem SQL-Statement. Ich möchte zwei Views zu einem View zusammenführen.
Es handelt sich um zwei Tabellen mit einer Artikel-ID und einer Stückzahl. Eine Artikel ID kann in beiden Tabellen vorkommen, muss es aber nicht. Kommt sie in einer Tabelle nicht vor, so hat sie die Stückzahl "0" (statt "null").
Die Grafik sollte das in etwa verdeutlichen.
Wie muss mein Statement aussehen?
_____________________________
Gruß
Carlo

oma

Hallo Carlo,

soll das ein einmaliger Vergang sein oder soll das permanent mit neuen Daten realisiert werden?

Gruß Oma
nichts ist fertig!

C4RL0

Zitat von: oma am Januar 22, 2014, 18:09:08
soll das ein einmaliger Vergang sein oder soll das permanent mit neuen Daten realisiert werden?

Hallo oma,

das soll ein dauerhafter dynamischer Vorgang werden.
_____________________________
Gruß
Carlo

oma

Hallo,

ich denke, dass wird nicht mit einem SQL-Statement zu realisieren sein (?).

Mit VBA wäre eine Variante möglich:

Du erstellt in Tabelle1 zusätzlich das Feld AnzahlB
Dann führst du folgende Funktion aus:

Public Function Ergaenzen()
On Error GoTo Err_Fehler

Dim rs1 As Recordset, rs2 As Recordset, rs3 As Recordset
Set rs1 = DBEngine(0)(0).OpenRecordset("SELECT * From Tabelle1")
Set rs2 = DBEngine(0)(0).OpenRecordset("SELECT * From Tabelle2")


rs2.MoveFirst  'ID aus Tabelle2, die nicht in Tabelle1 sind, dort einsetzen
    Do While rs2.EOF = False
    Set rs3 = DBEngine(0)(0).OpenRecordset("SELECT * From Tabelle1 WHERE ID='" & rs2!ID & "'")
       
        If rs3.RecordCount = 0 Then
            rs1.AddNew
            rs1!ID = rs2!ID
            rs1!AnzahlA = 0
            rs1!AnzahlB = rs2!AnzahlB
            rs1.Update
        End If
    rs2.MoveNext
Loop

rs1.MoveFirst  ' Wenn ID in A und B gleich, dann AnzahlB nach Tabelle 1 kopieren
Do While rs1.EOF = False
        rs2.MoveFirst
        Do While rs2.EOF = False
            If rs2!ID = rs1!ID Then
                If IsNull(rs1!AnzahlB) Or rs1!AnzahlB = "" Or rs1!AnzahlB = 0 Then
                    rs1.Edit
                        rs1!AnzahlB = rs2!AnzahlB
                    rs1.Update
                End If
             End If
         rs2.MoveNext
        Loop
rs1.MoveNext
Loop

rs1.MoveFirst   ' in Tabelle 1 alle Null mit 0 auffüllen
Do While rs1.EOF = False
        If IsNull(rs1!AnzahlB) Then
            rs1.Edit
            rs1!AnzahlB = 0
            rs1.Update
        End If
rs1.MoveNext
Loop

exit_Err_Fehler:
Exit Function

Err_Fehler:
MsgBox Err.Description, vbInformation, "Fehler"
Resume exit_Err_Fehler
End Function


Evt. ist das noch zu vereinfachen. Ob alle Varianten damit erschlagen werden, musst du mal mit kleineren Beispieltabellen testen

Gruß Oma
nichts ist fertig!

ebs17

Gehen würde es schon, etwa:
SELECT
    U.ID,
    IIf(T1.AnzahlA Is Null, 0, T1.AnzahlA) AS AnzahlA,
    IIf(T2.AnzahlB Is Null, 0, T2.AnzahlB) AS AnzahlB
FROM
    (
        (
            SELECT
                ID
            FROM
                Tabelle1
            UNION
                SELECT
                ID
            FROM
                Tabelle2
        ) AS U
            LEFT JOIN Tabelle1 AS T1
            ON U.ID = T1.ID
    )
    LEFT JOIN Tabelle2 AS T2
    ON U.ID = T2.ID


Allerdings ist das ein ganz schöner Krampf. Ich würde mich eher dafür interessieren, wer woraus solche Views erzeugt. Wenn man eine Abfragelogik auf die eigentliche(n) Tabelle(n) aufsetzt, kann das durchaus sinnvoller sein.
Mit freundlichem Glück Auf!

Eberhard

C4RL0

#5
Zitat von: ebs17 am Januar 23, 2014, 00:04:35Wenn man eine Abfragelogik auf die eigentliche(n) Tabelle(n) aufsetzt, kann das durchaus sinnvoller sein.

Wir können es ja mal probieren. Die Abfrage für die beiden views gestaltet sich wie folgt:

SELECT        T2.trkZiel AS [Abteilungs ID], T4.abtName AS Abteilung, COUNT(T2.trkID) AS Anzahl
FROM            dbo.tblTrack AS T2 INNER JOIN
                             (SELECT        trkIdentifikation AS ID, MAX(trkZeitstempel) AS MaxZeitstempel
                               FROM            dbo.tblTrack AS T1
                               GROUP BY trkIdentifikation) AS T3 ON T2.trkZeitstempel = T3.MaxZeitstempel INNER JOIN
                         dbo.tblAbteilungen AS T4 ON T2.trkZiel = T4.abtID
WHERE        (T2.trkZiel NOT LIKE 'SAP') AND (T2.trkZiel NOT LIKE 'JUN') AND (T2.trkDokumentenArt NOT LIKE 'HLA')
GROUP BY T2.trkZiel, T4.abtName


Exakt diese letzte Bedingung (T2.trkDokumentenArt NOT LIKE 'HLA') ist es, die ich in zwei spalten haben möchte, also einmal "NOT HLA" und einmal "HLA".
Bislang habe ich dieses über zwei views laufen, möchte das aber wie oben beschrieben konsolidieren.

Das ersetzen von "Null" durch "0" ist dabei nur ein kleines Extra, das kann ich auch im Code abfangen. K.A. was jetzt elegenter ist.
_____________________________
Gruß
Carlo

oma

Hallo,

das mit der VBA-Lösung ist natürlich ein ganz schöner Krampf aber die Lösung von ebs ist doch sauber!

Gruß Oma
nichts ist fertig!

ebs17

So ohne Daten fehlt es mir etwas an Abstraktion, was im Detail zu tun wäre. Das Grundprinzip kannst Du aber vom oberen Vorschlag ableiten: Du bräuchtest drei Teilabfragen.

Die erste stellt die vollständige Menge von trkZiel her, die zweite und die dritte zählen jeweils die DS nach Kriterien. Jede Abfrage selbstredend möglichst schlank und nur mit notwendigen Feldern für genau die beschriebene Berechnung, zzgl. der für die spätere  Verknüpfung notwendigen Schlüssel. Per LEFT JOIN werden dann die Zählabfragen an die erste angebunden.

Die Anbindung von ergänzenden Angaben aus der eigenen Tabelle sowie aus weiteren (dbo.tblAbteilungen) erfolgt dann erst in oberster Ebene. Prinzip: Erst Rechnen, dann Darstellen.

Krampf (oben) heißt: Da werden viel zu viele Zwischenschritte unternommen und unnötige Daten mitgeführt (großes Recordset, muss vielleicht in Teilen aus dem Arbeitssspeicher auf die Festplatte geschrieben werden => Performanceverlust / UNION-Abfrage bricht Indexnutzung => Performanceverlust / viel zu viel Berechnungsaufwand in den Teilabfragen => Kosten).
Mit freundlichem Glück Auf!

Eberhard

C4RL0

Hallo zusammen,

es hat etwas gedauert, aber ich habe es schließlich ausprobiert wie ebs17 es in Antwort 4 angeregt hatte.
Es klappt wunderbar, vielen Dank!
_____________________________
Gruß
Carlo