Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.
Dass gespeicherte Abfragen selbst wieder als Pseudotabellen in andere Abfragen integriert und dort mit anderen Tabellen verknüpft werden können, dürfte Ihnen bekannt sein. Weniger verbreitet jedoch sind jene Abfragen, die ungespeichert als SQL-Ausdruck zur Berechnung von Feldinhalten und Bedingungen dienen. Diese mit den Schlagwörtern Unterabfrage oder Subselect bezeichneten Ausdrücke sind Gegenstand dieses Beitrags.
Beispieldatenbank
Die Beispiele dieses Artikels finden Sie in der Datenbank 1604_Unterabfragen.accdb
Unterabfragen, Subselects
Eine Unterabfrage (engl. Subselect) ist nichts weiter, als eine vollständige in SQL geschriebene Auswahlabfrage, deren Ergebnis oder Ergebnisse zur Anzeige eines einzelnen Felds oder zur Bestimmung eines Auswahlkriteriums in einer anderen Abfrage dienen. Im Folgenden verwenden wir einige Beispiele, um verschiedene Möglichkeiten im Umgang mit diesen Unterabfragen zu demonstrieren.
Grundlage für die Beispieldatenbank ist das Datenmodell in Bild 1, welches Kunden und deren Bestellungen verwaltet. Neben den Kundendaten, bestehend aus der Tabelle tblKunden und deren Nachschlagetabellen tblAnreden, tblOrte und tblLaender, sind die Bestellungen in der Tabelle tblBestellungen festgehalten und zu jeder Bestellposition jeweils ein Datensatz in der Tabelle tblBestelldetails. Die Artikel jeder Bestellposition kommen schließlich aus der Nachschlagetabelle tblArtikel.
Bild 1: Beziehungen zwischen Kunden und deren Bestellungen im Datenmodell der Beispieldatenbank
Auswertungen über Subselects
Eine Anforderung an eine Auswertung könnte nun sein, die Anzahl von Bestellungen in einer übersicht darzustellen, die jeder Kunde getätigt hatte. Die dafür geeignete Abfrage wäre eine Gruppierungs– beziehungsweise Aggregatabfrage. Bild 2 zeigt, wie Sie diese gestalten könnten. Aus der Kundentabelle entnehmen wir lediglich die ID der Datensätze und den vollständigen Namen Kunde, welcher sich aus Nachname und Vorname zusammensetzt:
Bild 2: Die Abfrage gibt nur jene Kunden aus, die mindestens einmal bestellten
...Nachname & ', ' & Vorname AS Kunde
Um die Anzahl von Bestellungen zu jedem Kunden zu ermitteln, wird die Tabelle tblBestellungen mit der Kundentabelle 1:1 verknüpft. Die Berechnung der Anzahl erfordert als Aggregat, dass Sie aus der Abfrage eine Gruppierungsabfrage machen, indem Sie das Summensymbol ? im Entwurfs-Ribbon anklicken. Für die nun eingeblendete Zeile Funktion geben Sie bei ID und Kunde die Gruppierung an, und beim Feld Anzahl Bestellungen die ID von tblBestellungen, sowie die Funktion Anzahl. Die Bedingung, dass diese Anzahl größer, als 0, sein muss, ist eigentlich überflüssig, denn durch die 1:1-Verknüpfung werden ohnehin alle Datensätze ausgefiltert, die keinen Bezug zwischen den Tabellen besitzen.
Im Ergebnis haben Sie nun alle Kunden, die überhaupt etwas bestellten und die Gesamtzahl ihrer Bestellungen. Sie könnten noch nach diesem Feld absteigend sortieren, um die Top-Besteller zu ermitteln.
Diese Auswertung lässt sich aber auch anders realisieren. Statt die Tabelle tblBestellungen direkt in den Abfrageentwurf zu ziehen, wird sie in einen SELECT-Ausdruck als Unterabfrage integriert, der das Ausgabefeld Anzahl Bestellungen speist. Wie das aussieht, zeigt Bild 3. Hier wird bereits deutlich, dass solche Abfragen in der Entwurfsansicht etwas schwieriger zu handeln sind, da die SQL-Ausdrücke für die Unterabfragen relativ lang ausfallen und damit die Spaltenbreite dieser berechneten Felder ziemlich breit aufgezogen werden müsste. Entweder Sie verwenden dann die Zoom-Funktion für das Feld (rechter Mausklick), oder Sie schalten besser gleich in die SQL-Ansicht, die den Code von Listing 1 zutage fördert. Das Ergebnisfeld Anzahl Bestellungen ist hier mit n bezeichnet. Es errechnet sich über die Aggregatfunktion COUNT(*) auf die Datensätze von tblBestellungen. Da wir ja aber nicht für jeden Kunden die Gesamtzahl aller Bestellungen ausgeben möchten, sondern nur die Zahl seiner Bestellungen, braucht es noch eine zusätzliche WHERE-Bedingung. Pro Kundendatensatz müssen die Bestellungen gemäß seiner ID gefiltert werden.
Bild 3: Auch hier zeigen sich nur Kunden mit Bestellungen, jedoch mit Unterabfrage
Hier kommt nun ein Trick ins Spiel: Die Tabelle tblBestellungen wird in den Alias-Namen TMP umbenannt. Auf ihr Feld KundeID können Sie somit über TMP.KundeID Bezug nehmen. Ihr Wert muss mit der ID der Tabelle tblKunden übereinstimmen, damit die Filterung greift. Also setzen Sie diese Bedingung ein:
...WHERE TMP.KundeID = tblKunden.ID
Das Ergebnis stimmt mit dem der Abfrage aus Bild 2 überein.
Man könnte meinen, dass die Performance dieser Abfrage darunter litte, dass für jeden Kundendatensatz die Unterabfrage zur Anzahlberechnung erneut ausgeführt werden muss. Tatsächlich unterscheidet sie sich nicht nennenswert von der gruppierten Abfrage oben, denn auch bei Aggregatabfragen muss intern für jeden Datensatz eine eigene neue Berechnung durchgeführt werden.
Nummerieren
Der prominenteste Vertreter von Unterabfragen ist die Lösung zum Durchnummerieren der ausgegebenen Datensätze. Sie möchten etwa alle Kunden der Datenbank ausgeben und die Datensätze fortlaufend nummerieren. Unter Excel wäre das ein leichtes Unterfangen. Sie fügten hier einfach ganz vorn eine zusätzliche Spalte ein, schrieben eine 1 und eine 2 in die beiden ersten Zellen hinein und zögen die Spalte nach Markierung dieser zwei Zellen über die ganze Kundentabelle auf.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
Testzugang
eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel
diesen und alle anderen Artikel mit dem Jahresabo