Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

SQL,Access: Mehrere Tabellen mit gleicher Struktur bzw. Spalten zusammenführen

Frage Entwicklung Datenbanken

Mitglied: PSaR04

PSaR04 (Level 1) - Jetzt verbinden

04.07.2014 um 23:36 Uhr, 6420 Aufrufe, 5 Kommentare

Hallo,

ich habe eine zugegebener Weise nicht so tolle Access Datenbank bekommen, aus der ich Daten rausziehen muss. In der DB gibt es Tabellen, die DatenXX heißen. XX steht hierbei für die Kurzform von Jahreszahlen (das sollte wohl der Übersichtlichkeit dienen). Die Tabellen haben ansonsten alle die gleiche Struktur bzw. Spaltenbezeichnungen. Eine Spalte heißt jahrgang und ich benötige nun alle Datensätze, bei denen das Feld "jahrgang" leer ist. Für eine einzelne Tabelle ist das ja recht schnell gemacht, ich benötige die Datensätze nun aber aus allen Tabellen bei denen jahrgang leer. Die entsprechenden Datensätze aus allen Tabellen sollen in der Ausgabe dann einfach untereinander geschrieben werden.
Bei zwei Tabellen würde ich das einfach so machen:
01.
SELECT * FROM (SELECT * FROM Daten00 UNION ALL SELECT * FROM Daten01) WHERE jahrgang is null;
Doch was ist die eleganteste Möglichkeit die Datensätze aus allen Tabellen (Daten00 - Daten99) zusammenzuführen? 98 UNIONs? Da meckert Access garantiert, dass die Abfrage zu komplex ist. Gibt es eine Möglichkeit mit einem Range-Operator oder so zu arbeiten, der mir nicht bekannt ist? Also z. B. SELECT * FROM RANGE Daten$XX (00,99,1) WHERE....

Ich freue mich auf eure Tipps.

Grüße
PSaR04
Mitglied: colinardo
LÖSUNG 05.07.2014, aktualisiert um 18:00 Uhr
Hallo PSaR04,
mit VBA hätte ich dafür eine Lösung. Es fasst alle deine gewünschten Daten in einer neu erstellten Tabelle zusammen, und öffnet diese zum Schluss.
01.
Sub MergeTablesIntoOne() 
02.
    Dim rsAll As Recordset, rsCurrent As Recordset, tblName as String, c as integer, i as integer    
03.
    DoCmd.SetWarnings False 
04.
    ' passende Datensätze aus Daten00 in neue Tabelle schreiben 
05.
    DoCmd.RunSQL "Select * into DataResult from Daten00 where jahrgang is null" 
06.
    DoCmd.SetWarnings True 
07.
    ' neue Tabelle öffnen 
08.
    Set rsAll = CurrentDb.OpenRecordset("Select * From DataResult", dbOpenDynaset) 
09.
    Set db = CurrentDb 
10.
    ' Für alle passenden Tabellen 
11.
    For i = 1 To 99 
12.
        tblName = "Daten" & Right("0" & i, 2) 
13.
        Set rsCurrent = db.OpenRecordset("Select * From " & tblName & " where jahrgang is null", dbOpenSnapshot) 
14.
        rsCurrent.MoveFirst 
15.
        While Not rsCurrent.EOF 
16.
            rsAll.AddNew 
17.
            For c = 0 To rsAll.Fields.Count - 1 
18.
                rsAll.Fields(c).Value = rsCurrent.Fields(c).Value 
19.
            Next 
20.
            rsAll.Update 
21.
            rsCurrent.MoveNext 
22.
        Wend 
23.
    Next 
24.
    ' neu erstellte Tabelle anzeigen 
25.
    DoCmd.OpenTable "DataResult" 
26.
End Sub
Grüße Uwe
Bitte warten ..
Mitglied: PSaR04
05.07.2014 um 17:55 Uhr
Hallo colinardo!

Vielen Dank für den Programmcode, ich hatte gar nicht mit einer so ausführlichen Lösung gerechnet. Das hat mir bestimmt 2 Stunden Arbeit gespart, da ich mit VBA bisher noch nicht so viel gemacht habe.
Anhand der doch relativ aufwendigen Lösung gehe ich dann davon aus, dass sich die gewünschte Abfrage nicht einfacher realisieren lässt (etwa über einen mir unbekannten Operater oder ähnlichem, wie im ersten Post von mir gehofft)?!?
Ich musste deinen Quellcode nur noch an 2 Stellen etwas anpassen, da es zu Fehlern gekommen ist.
1. Bei der Deklaration der Recordsets rsAll und rsCurrent musste ich den Datentyp von "Recordset" auf "DAO.Recordset" ändern. Da es sonst zur Fehlermeldung "Typen unverträglich" kam.
2. Einige der Tabellen sind leer, daher musste ich noch ein "If Not rsCurrent.RecordCount = 0 Then..." ergänzen.

Hier der komplette Quellcode:
01.
Sub MergeTablesIntoOne() 
02.
    Dim rsAll As DAO.Recordset, rsCurrent As DAO.Recordset, tblName as String, c as integer, i as integer    
03.
    DoCmd.SetWarnings False 
04.
    ' passende Datensätze aus Daten00 in neue Tabelle schreiben 
05.
    DoCmd.RunSQL "Select * into DataResult from Daten00 where jahrgang is null" 
06.
    DoCmd.SetWarnings True 
07.
    ' neue Tabelle öffnen 
08.
    Set rsAll = CurrentDb.OpenRecordset("Select * From DataResult", dbOpenDynaset) 
09.
    Set db = CurrentDb 
10.
    ' Für alle passenden Tabellen 
11.
    For i = 1 To 99 
12.
        tblName = "Daten" & Right("0" & i, 2) 
13.
        Set rsCurrent = db.OpenRecordset("Select * From " & tblName & " where jahrgang is null", dbOpenSnapshot) 
14.
        If Not rsCurrent.RecordCount = 0 Then 
15.
            rsCurrent.MoveFirst 
16.
            While Not rsCurrent.EOF 
17.
                rsAll.AddNew 
18.
                For c = 0 To rsAll.Fields.Count - 1 
19.
                    rsAll.Fields(c).Value = rsCurrent.Fields(c).Value 
20.
                Next 
21.
                rsAll.Update 
22.
                rsCurrent.MoveNext 
23.
            Wend 
24.
        End If 
25.
    Next 
26.
    ' neu erstellte Tabelle anzeigen 
27.
    DoCmd.OpenTable "DataResult" 
28.
End Sub
Vielen Dank nochmal.
PSaR04
Bitte warten ..
Mitglied: colinardo
05.07.2014, aktualisiert um 18:15 Uhr
1. Bei der Deklaration der Recordsets rsAll und rsCurrent musste ich den Datentyp von "Recordset" auf "DAO.Recordset" ändern. Da es sonst zur Fehlermeldung "Typen unverträglich" kam.
OK, dann handelt es sich vermultich um eine ältere Access Datenbank. In neueren ist ADO Standard.

Anhand der doch relativ aufwendigen Lösung gehe ich dann davon aus, dass sich die gewünschte Abfrage nicht einfacher realisieren lässt (etwa über einen mir unbekannten Operater oder ähnlichem, wie im ersten Post von
Wart mal ab vielleicht hat der @Biber da eventuell noch eine Lösung für eine reine SQL Abfrage.

Grüße Uwe
Bitte warten ..
Mitglied: Biber
LÖSUNG 05.07.2014, aktualisiert 06.07.2014
Moin PSaR04 und colinardo,

um die Zweifel auszuräumen:
- es existiert weder in Access-SQL noch einem anderem SQL-Dialekt etwas wie "Mach mir einen UNION über Tabelle 1...n"
- wie PSaR04 schon richtig vermutete - Access würde bei 99 Tabellen in einer Query auch bedauernd abwinken, da bei 32 offenen Tabellen in einer Query Schicht ist (Okay, ist an dieser Stelle mal kein Vorwurf an die PraktikantInnen. Wenn mehr als 32 Tabellen in einer Query verbaut werden müssen, dann ist das Datenbankdesign marode, so wie ja auch in dieser "Ich mach ma' 100 Tabellen, weil ich 100 Jahre verwalten will"-Musterlösung).


Einziger Verbesserungsvorschlag, den ich zum Skript anbringen würde:

Ich würde sicherheitshalber ein Feld mehr ins Resultset übernehmen, damit ich weiss, aus welcher Tabelle der Satz stammt.
Also statt
Set rsCurrent = db.OpenRecordset("Select * From " & tblName & " where jahrgang is null",

etwa so
Set rsCurrent = db.OpenRecordset("Select ' " & tblname & " ' as Tbname, t.* From " & tblName &" as t where jahrgang is null",


Falls die Abfragen auf die 99 Tabellen noch auf andere Fragestellungen modifiziert werden sollen:

Dann würde ich die Daten aus den Tabellen 1..99 nicht nur jetzt einmalig in einen Resultset schaufeln, sondern gleich- wenn ich eh' alle Tabellen durchwackeln muss- den ganzen Quatsch in eine neue Tabelle schreiben. Mit allen Sätzen, ohne einschränkendes WHERE.

Und eben mit einem Zusatzfeld, in dem der Quelltabellenname steht.

Grüße
Biber
Bitte warten ..
Mitglied: PSaR04
06.07.2014 um 16:59 Uhr
Zitate von colinardo:

OK, dann handelt es sich vermultich um eine ältere Access Datenbank. In neueren ist ADO Standard.
Ja, es handelt sich um eine Datenbank, die glaube ich unter Access 2000 entwickelt wurde.


Zitate von Biber:
- es existiert weder in Access-SQL noch einem anderem SQL-Dialekt etwas wie "Mach mir einen UNION über Tabelle 1...n"
Ok, danke für die Bestätigung. Ich konnte mir das auch fast nicht vorstellen, da ich trotz intensiver Suche nichts dazu gefunden habe, aber gut jetzt Gewissheit zu haben.

Wenn mehr als 32 Tabellen in einer Query verbaut werden müssen, dann ist das Datenbankdesign marode, so wie ja auch in dieser "Ich mach ma' 100 Tabellen, weil ich 100 Jahre verwalten will"-Musterlösung).
Da stimme ich dir voll und ganz zu. Die DB soll jetzt auch schnellstmöglich abgelöst werden, hat schon genug Nerven gekostet. Es handelt sich bei der benötigten Abfrage schon um eine vorbereitende Maßnahme dafür.

Ich würde sicherheitshalber ein Feld mehr ins Resultset übernehmen, damit ich weiss, aus welcher Tabelle der Satz stammt.
Ja, daran hatte ich auch schon gedacht, bisher ist das aber nicht wichtig. Aber gut, dass du die Lösung dafür schon gleich gepostet hast, kann ich bestimmt noch gebrauchen.
Dann würde ich die Daten aus den Tabellen 1..99 nicht nur jetzt einmalig in einen Resultset schaufeln, sondern gleich- wenn ich eh' alle Tabellen durchwackeln muss- den ganzen Quatsch in eine neue Tabelle schreiben. Mit allen Sätzen, ohne einschränkendes WHERE.
Wenn noch mehr Abfragen notwendig werden, mache ich das. Bisher ist das aber noch nicht abzusehen.


Vielen Dank, ihr habt mir sehr weitergeholfen!
PSaR04
Bitte warten ..
Neuester Wissensbeitrag
Microsoft

Lizenzwiederverkauf und seine Tücken

(5)

Erfahrungsbericht von DerWoWusste zum Thema Microsoft ...

Ähnliche Inhalte
LAN, WAN, Wireless
gelöst Access Points mit gleicher SSID Bereitstellen? (7)

Frage von KMUlife zum Thema LAN, WAN, Wireless ...

Microsoft Office
Access Verknüpfte Tabellen Passwort ändern

Frage von mijacd zum Thema Microsoft Office ...

VB for Applications
Mehrere Spalten Durchsuchen und Ergebnisse in neuer Tabelle Ausgeben (3)

Frage von Mr.Green zum Thema VB for Applications ...

Heiß diskutierte Inhalte
Windows Server
Outlook Verbindungsversuch mit Exchange (15)

Frage von xbast1x zum Thema Windows Server ...

Microsoft Office
Keine Updates für Office 2016 (13)

Frage von Motte990 zum Thema Microsoft Office ...

Grafikkarten & Monitore
Tonprobleme bei Fernseher mit angeschlossenem Laptop über HDMI (11)

Frage von Y3shix zum Thema Grafikkarten & Monitore ...