pensar en términos de conjuntos, no iteradores; las instrucciones sql definen las propiedades del conjunto de salida deseado (también conocido como tabla / relación)
Todos los lugares Nombres de tal manera que para cada banda País hay una banda de ese país que toca en el lugar de ese nombre
El resultado de esto (¡si entendiera sus intenciones correctamente!) sería el conjunto de lugares que tienen al menos una banda que toca en ese lugar. La iteración sobre bandCountry es innecesaria, ya que la relación PLAYS ya tiene la información que busca, solo tiene que eliminar los duplicados
entonces en SQL esto sería:
select
distinct venueName
from PLAYS
EDITAR: ok, entonces el conjunto real deseado es un poco más complicado. La pregunta que se hace a la base de datos es: ¿qué lugares han acogido bandas de todos los países?
Por lo tanto, definimos los criterios de membresía para un elemento del conjunto deseado como el objetivo, luego trabajamos hacia atrás para completar el conjunto. Un lugar es un miembro del conjunto de salida si tiene una fila PLAYS para al menos una banda de cada país. ¿Cómo obtenemos esta información?
Una forma es contar los distintos países para cada lugar y compararlo con el recuento de todos los países. Pero no tenemos una relación PAÍS. Si pensamos en el modelo dado por un momento, vemos que el conjunto de todos los países no es el criterio correcto; Es el conjunto de todos los países que tienen al menos una banda. Por lo tanto, no necesitamos una tabla de países (aunque para un modelo normalizado deberíamos tener una), y no nos importa el país del lugar, solo podemos contar los países que tienen bandas, por ejemplo (en MS-SQL )
declare @BandCountryCount int
select
@BandCountryCount = COUNT(distinct bandCountry)
from BAND
Podemos contar los países de la banda para cada lugar
select
P.venueName, COUNT(distinct B.bandCountry) as VenueBandCountryCount
from PLAYS P
inner join BAND B on B.bandName = P.bandName
y podemos juntar los dos usando una subconsulta
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
Ahora, esa no es la consulta más bonita posible (GROUP BY y HAVING podrían considerarse una solución más 'elegante' que las variables temporales y una subconsulta) pero es bastante obvio lo que buscamos, así que lo dejaremos así para el propósito del OP .
El objetivo del OP era aprender cómo cambiar la mentalidad de imperativo a declarativo. Con ese fin, observe lo que estaba haciendo la solución imperativa descrita:
para cada nombre de lugar iterar sobre todos los BandCountries y para cada bandCountry obtener la lista de bandas que provienen de él. Si ninguno de ellos juega en el nombre del lugar, vaya al siguiente nombre del lugar. De lo contrario, al final de la iteración bandCountries, agregueplaceName al conjunto de buenos lugaresNames
¿Cuál es el criterio determinante en lo anterior? Creo que es:
... Si ninguno de ellos [el conjunto de bandas de un país en particular] toca en el lugar Nombre ...
Este es un criterio descalificador . El proceso de pensamiento imperativo está comenzando con un balde lleno y tirando cosas que no cumplen con los criterios. Estamos filtrando datos.
Eso está bien para cosas simples, pero ayuda a pensar en términos de construir el conjunto de resultados deseado; ¿Cuál es el criterio de calificación correspondiente que le permitiría llenar el balde?
- descalificador: si no hay una banda de un país de banda que toca en un lugar, el lugar está descalificado
- calificador (parcial): si al menos una banda de un bandCountry toca en un lugar, entonces el lugar podría estar bien; sigue revisando el resto de la banda
- calificador (completo): si al menos una banda de cada grupo juega en un lugar, entonces el lugar está calificado
El calificador final se puede simplificar usando conteos: un país de banda está 'satisfecho' si al menos una banda de allí toca en un lugar; el número de países de banda "satisfechos" para un lugar debe ser igual al número de países de banda para que el lugar sea calificado.
Ahora podemos razonar a través de las relaciones por navegación:
- comenzar con la relación VENUE [no la necesitamos para la respuesta, pero es el punto de partida conceptual para la navegación relacional]
- únete a PLAYS en el lugar
- únete a BAND en bandName para obtener la banda
- no nos importa el nombre de la banda; seleccione solo el lugar Nombre y banda País
- no nos importan los BandCountries redundantes; eliminar duplicados usando DISTRICT o GROUP BY
- solo nos importa el recuento de distintos países de la banda, no los nombres
- solo queremos lugares donde el recuento de bandCountries distintos sea el mismo que el número total de bandCountries
que conduce de nuevo a la solución anterior (o un facsímil razonable de la misma)
RESUMEN
- teoría de conjuntos
- rutas de navegación relacionales
- criterios inclusivos vs exclusivos (calificativos vs descalificadores)