Denken Sie in Mengen, nicht in Iteratoren. Die SQL-Anweisungen definieren die Eigenschaften der gewünschten Ausgabemenge (auch bekannt als Tabelle / Relation).
alle venueNames so, dass es für jedes bandCountry eine Band aus diesem Land gibt, die am Veranstaltungsort dieses Namens spielt
das ergebnis davon (wenn ich deine absichten richtig verstanden habe!) wären die veranstaltungsorte, an denen mindestens eine band spielt. Die Iteration über bandCountry ist unnötig, da die PLAYS-Beziehung bereits die gesuchten Informationen enthält. Sie müssen nur die Duplikate entfernen
In SQL wäre dies also:
select
distinct venueName
from PLAYS
EDIT: ok, also das eigentlich gewünschte set ist etwas komplizierter. Die Frage, die der Datenbank gestellt wird, lautet: Welche Veranstaltungsorte haben Bands aus allen Ländern beherbergt ?
Also definieren wir die Mitgliedschaftskriterien für ein Element der gewünschten Menge als Ziel und arbeiten dann rückwärts, um die Menge zu füllen. Ein Veranstaltungsort ist Mitglied des Output-Sets, wenn es eine PLAYS-Zeile für mindestens eine Band aus jedem Land gibt. Wie erhalten wir diese Informationen?
Eine Möglichkeit besteht darin, die verschiedenen Länder für jeden Veranstaltungsort zu zählen und mit der Anzahl aller Länder zu vergleichen. Wir haben aber keine LAND-Beziehung. Wenn wir für einen Moment über das gegebene Modell nachdenken, sehen wir, dass die Menge aller Länder nicht die richtigen Kriterien sind; Es ist die Menge aller Länder, die mindestens eine Band haben. Wir brauchen also keine Ländertabelle (obwohl wir für ein normalisiertes Modell eine haben sollten), und wir kümmern uns nicht um das Land des Veranstaltungsortes, wir können nur die Länder zählen, die Bands haben, z. B. (in MS-SQL) )
declare @BandCountryCount int
select
@BandCountryCount = COUNT(distinct bandCountry)
from BAND
Wir können die Bandländer für jeden Veranstaltungsort zählen
select
P.venueName, COUNT(distinct B.bandCountry) as VenueBandCountryCount
from PLAYS P
inner join BAND B on B.bandName = P.bandName
und wir können die beiden unter Verwendung einer Unterabfrage zusammenfügen
select
venueName
from (
select
P.venueName, COUNT(distinct B.bandCountry) as VenueBandCountryCount
from PLAYS P
inner join BAND B on B.bandName = P.bandName
) X
where X.VenueBandCountryCount = @BandCountryCount
Nun, das ist nicht die schönste mögliche Abfrage (GROUP BY und HAVING können als elegantere Lösung angesehen werden als temporäre Variablen und Unterabfragen), aber es ist ziemlich offensichtlich, wonach wir suchen .
Ziel des OP war es, zu lernen, wie die Denkweise von imperativ zu deklarativ geändert werden kann. Schauen Sie sich zu diesem Zweck an, was die beschriebene Imperativlösung tat:
für jeden venueName werden alle bandCountries durchlaufen und für jedes bandCountry wird die Liste der davon stammenden Bands angezeigt. Wenn keiner von ihnen in venueName spielt, gehe zum nächsten venueName. Andernfalls wird am Ende der Iteration von bandCountries venueName zum Satz guter venueNames hinzugefügt
Was ist das bestimmende Kriterium in den oben genannten? Ich denke, es ist:
... Wenn keine von ihnen [die Gruppe von Bands aus einem bestimmten Land] in venueName spielt ...
Dies ist ein Disqualifikationskriterium . Der imperative Denkprozess beginnt mit einem vollen Eimer und dem Wegwerfen von Dingen, die nicht den Kriterien entsprechen. Wir filtern Daten heraus.
Für einfache Dinge ist das in Ordnung, aber es hilft, die gewünschte Ergebnismenge zu konstruieren. Was sind die entsprechenden Qualifikationskriterien , anhand derer man stattdessen den Eimer füllen kann?
- Disqualifier: Wenn es keine Band aus einem Bandland gibt, die an einem Veranstaltungsort spielt, wird der Veranstaltungsort disqualifiziert
- (Teil-) Qualifier: Wenn mindestens eine Band aus einem bandCountry an einem Veranstaltungsort spielt, ist der Veranstaltungsort möglicherweise in Ordnung. Überprüfe weiterhin den Rest der BandCountries
- (Full) Qualifier: Wenn mindestens eine Band aus jedem BandCountry an einem Veranstaltungsort spielt, ist der Veranstaltungsort qualifiziert
Das finale Qualifikationsspiel kann durch Zählungen vereinfacht werden: Ein bandCountry ist "zufrieden", wenn mindestens eine Band von dort an einem Veranstaltungsort spielt; Die Anzahl der "zufriedenen" Bandländer für einen Veranstaltungsort muss der Anzahl der Bandländer entsprechen, in denen sich der Veranstaltungsort qualifiziert.
Jetzt können wir durch Navigation über Beziehungen hinweg argumentieren:
- beginne mit der VENUE-Relation [wir brauchen sie nicht für die Antwort, aber sie ist der konzeptionelle Ausgangspunkt für die relationale Navigation]
- trete PLAYS auf venueName bei
- trete BAND auf bandName bei, um das bandCountry zu erhalten
- Der Bandname ist uns egal. wähle nur den venueName und das bandCountry
- redundante bandCountries interessieren uns nicht; Entfernen Sie doppelte Einträge mit DISTRICT oder GROUP BY
- Wir kümmern uns nur um die Anzahl der verschiedenen Band-Länder, nicht um die Namen
- Wir wollen nur Veranstaltungsorte, bei denen die Anzahl der verschiedenen Bandländer der Gesamtzahl der Bandländer entspricht
Dies führt zurück zu der obigen Lösung (oder einem vernünftigen Faksimile davon).
ZUSAMMENFASSUNG
- Mengenlehre
- relationale Navigationspfade
- inklusive vs. exklusive Kriterien (Qualifikation vs. Disqualifikation)