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?
Hallo Carlo,
soll das ein einmaliger Vergang sein oder soll das permanent mit neuen Daten realisiert werden?
Gruß Oma
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.
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
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.
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.abtNameExakt 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.
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
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).
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!