pensare in termini di set, non di iteratori; le istruzioni sql definiscono le proprietà del set di output desiderato (aka tabella / relazione)
tutti i nomi dei locali in modo tale che per ogni band Paese ci sia una band di quel paese che suona in quel luogo
il risultato di questo (se ho capito bene le tue intenzioni!) sarebbe l'insieme di locali che hanno almeno una band che suona in quel locale. L'iterazione su bandCountry non è necessaria, poiché la relazione PLAYS ha già le informazioni che cerchi, devi solo eliminare i duplicati
quindi in SQL questo sarebbe:
select
distinct venueName
from PLAYS
EDIT: ok, quindi il set effettivo desiderato è un po 'più complicato. La domanda che viene posta al database è: quali locali hanno ospitato band di tutti i paesi?
Quindi, definiamo i criteri di appartenenza per un elemento dell'insieme desiderato come obiettivo, quindi lavoriamo all'indietro per popolare l'insieme. Una sede è un membro del set di output se ha una riga PLAYS per almeno una band di ogni paese. Come otteniamo queste informazioni?
Un modo è contare i paesi distinti per ciascuna sede e confrontarlo con il conteggio di tutti i paesi. Ma non abbiamo una relazione COUNTRY. Se pensiamo al modello dato per un momento, vediamo che l'insieme di tutti i paesi non è il criterio giusto; è l'insieme di tutti i paesi che hanno almeno una banda. Quindi non abbiamo bisogno di una tabella dei paesi (anche se per un modello normalizzato dovremmo averne uno) e non ci interessa il paese della sede, possiamo semplicemente contare i paesi che hanno bande, ad esempio (in MS-SQL )
declare @BandCountryCount int
select
@BandCountryCount = COUNT(distinct bandCountry)
from BAND
Possiamo contare i paesi della band per ogni sede
select
P.venueName, COUNT(distinct B.bandCountry) as VenueBandCountryCount
from PLAYS P
inner join BAND B on B.bandName = P.bandName
e possiamo mettere insieme i due usando una sottoquery
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
Ora, questa non è la query più carina possibile (GROUP BY e HAVING potrebbero essere considerati una soluzione più "elegante" delle variabili temporanee e una subquery) ma è abbastanza ovvio ciò che stiamo cercando, quindi lo lasceremo allo scopo del PO .
Lo scopo del PO era quello di imparare a spostare la mentalità dall'imperativo al dichiarativo. A tal fine, guarda cosa stava facendo la soluzione imperativa descritta:
per ogni sede, dai un nome a tutte le bandCountries e per ogni bandCountry ottieni l'elenco delle band che ne derivano. Se nessuno di loro gioca nel nome del locale, vai al nome del luogo successivo. Altrimenti, alla fine della band, l'iterazione di Countuntries aggiunge venueName all'insieme di good venueNames
Quali sono i criteri determinanti in quanto sopra? Io penso che sia:
... Se nessuno di loro [l'insieme di band di un determinato paese] suona nel locale Nome ...
Questo è un criterio squalificante . Il processo di pensiero imperativo sta iniziando con un secchio pieno e gettando via cose che non soddisfano i criteri. Stiamo filtrando i dati.
Va bene per cose semplici, ma aiuta a pensare in termini di costruzione del set di risultati desiderato; quali sono i criteri di qualificazione corrispondenti che consentirebbero invece di riempire il secchio?
- squalificatore: se non esiste una band di una band Country che suona in una sede, la sede è squalificata
- qualificatore (parziale): se almeno una band di una band Country suona in una sede, la sede potrebbe essere ok; continua a controllare il resto della bandCountries
- qualificatore (completo): se almeno una band di ogni band Country suona in una sede, allora la sede è qualificata
Il qualificatore finale può essere semplificato usando i conteggi: una bandCountry è 'soddisfatta' se almeno una band da lì suona in un locale; il numero di paesi della band "soddisfatti" per una sede deve essere uguale al numero di paesi della band per la sede da qualificare.
Ora possiamo ragionare attraverso le relazioni tramite la navigazione:
- inizia con la relazione VENUE [non ne abbiamo bisogno per la risposta, ma è il punto di partenza concettuale per la navigazione relazionale]
- iscriviti a PLAYS in venueName
- unisciti a BAND su bandName per ottenere bandCountry
- non ci interessa il nome della band; seleziona solo la sede Nome e banda Paese
- non ci importa di BandCountries ridondanti; eliminare i duplicati utilizzando DISTRICT o GROUP BY
- ci preoccupiamo solo del conteggio di BandCountries distinti, non dei nomi
- vogliamo solo locali in cui il conteggio di bandCountries distinti è uguale al numero totale di bandCountries
che riporta alla soluzione sopra (o ad un ragionevole facsimile)
SOMMARIO
- insiemistica
- percorsi di navigazione relazionale
- criteri inclusivi vs esclusivi (qualificazioni vs squalifiche)