In der vorigen Ausgabe von Access [basics] schnitten wir das Thema UNION-Abfragen bereits an. Dort wurde ein Kombinationsfeld zur Formularnavigation mit einem UNION-SELECT-Ausdruck als Datenherkunft belegt. Deshalb nehmen wir diese SQL-Spezialität hier einmal etwas allgemeiner unter die Lupe und betrachten zusammengesetzte Abfragen im Detail.
Beispieldatenbank
Die Beispiele dieses Artikels finden Sie in der Datenbank 1603_Union-Abfragen.accdb
Daten zusammenfassen
In der Beispieldatenbank stellt sich eine Aufgabe, die so gar nicht selten zu erledigen ist: Daten verschiedener Herkunft sollen in einer Tabelle zusammengeführt werden. Es handelt sich um Adressen, die etwa aus importierten CSV-Dateien stammen und bereits in den Tabellen tblAdressen1 bis tblAdressen4 vorliegen.
Die erste enthält nur Adressen aus dem Postleitzahlengebiet 1* und 2*, die nächste aus 3*, 4* und 5*, eine weitere aus 6*, 7*, 8* und 9*, sowie schließlich eine für jene aus 0*. Die Datensätze dieser vier Tabellen transferieren wir nun in ihrer Gesamtheit in die Tabelle tblAdressen.
Hierfür könnten Sie eine einfache Anfügeabfrage erstellen und nacheinander die jeweiligen Quelltabellen in sie einsetzen, um den Export zu bewerkstelligen. Das allerdings ist wenig elegant und zieht so einiges Mausgeklicke nach sich, von der Fehleranfälligkeit einmal abgesehen. Besser, Sie greifen hier zu einer UNION-Abfrage, die die Sache in einem Rutsch erledigt.
UNION-Abfragen
Eine UNION-Abfrage fasst zwei oder mehr einzelne Abfragen in einem Ergebnis zusammen. Während Sie fast alle Abfragetypen mit dem GUI-Query-Editor anlegen und bearbeiten können, sieht das bei UNION-Abfragen anders aus. Hier sind Sie im Entwurf auf den SQL-Editor beschränkt. Ohne grundlegende SQL-Kenntnisse sind sie damit also nicht im Boot.
Bild 1 zeigt, wie Sie gespeicherte UNION-Abfragen im Navigationsbereich von Access sofort erkennen können. Das Schnittmengensymbol macht sie deutlich.
Bild 1: Die zwei Ringe stellen das Symbol für UNION-Abfragen im Navigationsbereich dar
Legen Sie Ihre erste UNION-Abfrage so an: Klicken Sie im Ribbon Erstellen auf Abfrageentwurf. Schließen Sie sofort den Dialog zur Tabellenauswahl. Der Ribbon-Tab Entwurf ist nun automatisch aktiv, und links wird auch gleich der Button SQL für die Ansicht eingeblendet. Klicken Sie darauf, um den SQL-Editor zu öffnen.
Nur als Hinweis hat Access bereits den Ausdruck Select; als SQL-Text im Editor eingefügt. Um nun alle Datensätze der Tabelle tblAdressen1 im Abfrageergebnis anzuzeigen, erweitern Sie den Ausdruck in
SELECT * FROM tblAdressen1
Da die Aufgabe darin besteht, zusätzlich zu dieser Tabelle auch noch eine weitere ins Ergebnis zu holen, benötigen wir ein weiteres SELECT-Statement, das diesmal aber über den Ausdruck UNION mit dem anderen SELECT-Statement verknüpft wird:
SELECT * FROM tblAdressen1 UNION SELECT * FROM tblAdressen2
Klicken Sie auf den Ausführen-Button im Ribbon, um sich davon zu überzeugen, dass diese Abfrage einwandfrei funktioniert. Speichern Sie sie unter dem Namen qry_Union_Simple ab. Im Navigationsbereich wird sie sogleich angezeigt und weist das entsprechende Symbol auf. Ein Rechtklick auf den Eintrag listet im Kontextmenü übrigens nun ebenfalls nur die SQL-Ansicht ein. Die normale Entwurfsansicht ist nicht erreichbar.
Eine UNION-Abfrage wird als solche allerdings nur identifiziert, wenn Sie den Aufbau von oben hat und Sie das Ergebnis nicht in Klammern einfassen. Denn auch diese Syntax ließe sich herstellen:
SELECT * FROM ( SELECT * FROM tblAdressen1 UNION SELECT * FROM tblAdressen2 )
Die eigentliche UNION-Abfrage ist hier innerhalb der Klammern zu finden und wird wie eine einzelne Tabelle behandelt, indem ein weiterer Select-Ausdruck auf diese Unterabfrage angewandt wird. Das Anzeigeergebnis ist zwar dasselbe, die Abfrage wird dabei jedoch als normale Auswahlabfrage gespeichert. Damit besteht automatisch auch die Möglichkeit, sie im Entwurfsmodus zu öffnen. Das sieht dann etwa aus, wie in Bild 2. In dieser Abfrage wurde das UNION-Ergebnis über das äußere Select-Statement noch einer Sortierung nach Namen unterzogen, sowie einer Filterung nach dem Postleitzahlenbereich 1*.
Bild 2: Dass es sich hier um eine UNION-Abfrage handelt, ist nicht gleich erkennbar
Das geht aus dem Entwurf zwar vor, irritierend ist aber die seltsame Tabellenbezeichnung [%$##@_Alias]. Access setzt diesen Ausdruck immer dann ein, wenn eine Unterabfrage nicht namentlich definiert ist. Sie können das etwa so ändern:
SELECT * FROM (
SELECT * FROM tblAdressen1
UNION
SELECT * FROM tblAdressen2
) As UTable
Hier wird das Klammerergebnis, die UNION-Abfrage, als virtuelle Tabelle UTable definiert, was anschließend auch im Entwurfsmodus zu sehen ist. Das [%$##@_Alias] macht dem UTable Platz. Indessen geht im Entwurf auch jetzt noch nicht hervor, dass die angezeigte Tabelle tatsächlich eine UNION-Abfrage darstellt. Erst das Schalten in den SQL-Modus lüftet das Geheimnis.
Sie können direkt auch mehrere Tabellen oder Abfragen in einer UNION-Abfrage zusammenführen.
Alle für unsere Zielabfrage benötigten Adresstabellen fügen sich so aneinander:
SELECT * FROM tblAdressen1 UNION SELECT * FROM tblAdressen2 UNION SELECT * FROM tblAdressen3 UNION SELECT * FROM tblAdressen4
Im Ergebnis stehen damit alle Adressen aller Postleitzahlenbereiche bereit.
Wie viele Tabellen in einer UNION-Abfrage eingebaut sein dürfen, steht nicht eindeutig fest. An sich gibt es die Aussage von Microsoft, dass eine Abfrage nicht mehr als 32 Tabellen enthalten darf. Entweder ist diese Information veraltet und spiegelt nicht mehr die Eigenschaften der Access Database Engine wider, oder für UNION gelten andere Regeln. Jedenfalls gelang es uns problemlos, auch 49 Adresstabellen aneinanderzufügen. Erst bei 50 und mehr kam es zur Fehlermeldung
Ausdruck oder Abfrage zu komplex
Es dürfte auch von der Anzahl der Felder der Quelltabellen abhängen, wann diese Meldung auf den Plan tritt.
übrigens können sie die gleiche Tabelle auch mehrmals mit sich selbst kombinieren:
SELECT * FROM tblAdressen1 UNION SELECT * FROM tblAdressen1
Man sollte hier erwarten, dass sich die Zahl der Datensätze gegenüber tblAdressen1 verdoppelt. Tatsächlich ist das nicht der Fall!
Der Grund dafür ist, dass Access im Ergebnis keine doppelten identischen Datensätze ausgibt, also zusätzlich ein DISTINCT ausführt. Der Ausdruck UNION bekommt damit ja auch die korrekte Bedeutung: Das Ergebnis ist die Mengensumme beider Tabellen! Allerdings können Sie dies aufheben, indem Sie nach UNION noch das Prädikat ALL setzen:
SELECT * FROM tblAdressen1 UNION ALL SELECT * FROM tblAdressen1
In diesem Fall werden tatsächlich alle Ausgangsdatensätze aneinander gereiht. Vorteil dieser Variante ist die bessere Performance. Access muss hier lediglich die Datensätze summieren, während ohne ALL noch die überprüfung auf Doppelungen stattfindet.
Sortierung und Filterung
Die kombinierten Datensätze können gleich innerhalb der UNION-Abfrage sortiert und gefiltert werden, indem die normalen ORDER BY-Statements oder WHERE-Bedingungen ans Ende des SQL-Ausdrucks gestellt werden:
SELECT * FROM tblAdressen1 UNION SELECT * FROM tblAdressen2 UNION SELECT * FROM tblAdressen3 WHERE PLZ LIKE "1*" ORDER BY Nachname;
Die drei Quelltabellen werden kombiniert und das Ergebnis schließlich der Filterung nach Postleitzahlengebiet 1 unterzogen, sowie aufsteigend nach Nachname sortiert.
Welche Anforderungen bestehen an die Ausgangstabellen
Die wichtigste Anforderung ist, dass die Zahl der Felder jeder Tabelle oder Abfrage übereinstimmen. Das gilt indessen nicht für die Namen der Felder. Auch der Datentyp spielt keine Rolle. Versuchen Sie etwa dies:
SELECT Nachname FROM tblAdressen1 UNION SELECT PLZ FROM tblAdressen2
Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein: