Conoce SQL – SELECT – Parte 2

En la primera parte sobre SELECT vimos básicamente como enlazar diferentes tablas y así aprovecharnos de las foreign key. Eso es lo mínimo que se debería saber ya que conociendo un poco por encima ese tema podemos hacer consultas bastante majas sin recurrir a complejos e ineficientes algoritmos en PHP.

Pero pronto vemos que se nos queda corto y queremos más pero que no cunda el pánico, aquí hay SQL para todos. En esta segunda parte de SELECT quiero tratar las subconsultas

Vaya, parece poco pero es más de lo que parece.

SUBCONSULTAS SQL

A veces nos surge la necesidad de hacer una consulta dentro de otra consulta. En SQL podemos meter un SELECT casi en cualquier sitio pero ahora me centrare en SELECTs dentro de SELECTs.

Voy a hacer una consulta muy tonta pero para ver a lo que me refiero con esto de las subconsultas. Simplemente voy a hacer una busqueda de paquetes de una ciudad, en este caso Palencia.

En principio podríamos hacerlo en PHP de esta manera:

$sql=”SELECT id_ciudad FROM ciudades WHERE ciudad=’Palencia'”;
while($fila=mysql_fetch_array(mysql_query($sql))
{
$sql=”SELECT codigo_paquete FROM paquetes WHERE id_ciudad=$fila[0]”;
while($fila2=mysql_fetch_array(mysql_query($sql))
{
echo $fila2[0];
}
}

Fíjate en el orden de las consultas. Primero obtenemos todas las id_ciudad y luego cojemos los paquetes con solo esa id_ciudad

$sql=”SELECT codigo_paquete FROM paquetes
WHERE id_ciudad=(SELECT id_ciudad FROM ciudades WHERE ciudad=’Palencia’)”;
while($fila=mysql_fetch_array(mysql_query($sql))
{
echo $fila[0];
}

Observa que en esta segunda consulta el orden es invertido. Primero “seleccionamos” todos los codigo_paquete y después especificamos que códigos queremos con la segunda consulta. En este tipo de consultas la lógica funciona de manera inversa, primero se pone lo mas concreto (codigo_paquete) y después se va generalizando (ciudades) mientras con el script php primero obtenemos los datos más genéricos (ciudades) y luego se va concretando (codigo_paquete).

Otra cosa importante es que esta subconsulta solo puede devolver un valor y del mismo tipo. Pero si lo piensas es lógico, id_ciudad es un número no varios números o un varchar. Que sea el mismo tipo de dato seguro que lo suponías pero un fallo común es que la subconsulta devuelva varios valores, entonces mysql te tira la consulta completa.

Te habrás dado cuenta de que esta consulta carece de sentido ya que usando JOIN no ahorramos todo este rollo, pero es solo un ejemplo de que una subconsulta no es más que una consulta dentro de otra consulta. Hasta aquí la única diferencia entre el algoritmo PHP y la consulta es la eficiencia (que no es poco) pero esque las subconsulta tienen más chicha, mira este par de cosillas simples pero que nos ahorrarían pensar complejos algoritmos PHP.

Para ver este ejemplo vamos a necesitar más objetos en la base de datos. Creamos esta tabla

CREATE TABLE ciudades_elegidas (
id_ciudad INT
)

Aquí lo ideal sería poner foreign key y clave primaria a id_ciudad pero como es una tabla que carece de sentido práctico pues lo haré de la manera más sencilla posible. También vamos a meter más datos

INSERT INTO ciudades (id_ciudad,ciudad) VALUES (3,’Zamora’),(4,’Barcelona’),(5,’Salamanca’),(6,’Segovia’),(7,’Valencia’)

y ahora vamos a meter unas ciudades en la tabla ciudades_elegidas

INSERT INTO ciudades_elegidas VALUES (0),(1),(3),(5),(6)

Te recuerdo que no te preocupes por los INSERT, es algo que veremos más adelante. Lo que he hecho ha sido meter los id_ciudad 0,1,3,5,6 en la tabla. Como dije antes, aquí lo correcto sería enlazar la columna id_ciudad de la tabla ciudades_elegidas con id_ciudad de ciudades para evitar meter una ciudad que no exista en nuestra base de datos. Pero lo que quería enseñarte es esto

SELECT ciudades FROM ciudades
WHERE id_ciudad IN (
SELECT id_ciudad FROM ciudades_elegidas
)

Esta consulta selecciona todas las ciudades y despues con la claúsula WHERE limitamos la búsqueda pero esta vez en vez depender de un solo valor (id_ciudad=5 por ejemplo) le estamos dando una lista de filas para que compare. El problema que teníamos antes de que solo se podía comparar con un dato está resuelto. De esta manera le decimos a mysql “Dame todas las ciudades que estan en esta lista”. Esto se hace con IN. Hay veces en los que estás seguro de una subconsulta te devolverá un valor, ese caso se puede usar el igual “=” pero si no estás seguro o sabes que devuelve varios valores entonces hay que usar el “IN”.

Si por el contrario queremos mostrar las ciudades que no estan en la lista no tenemos más que decir a mysql que nos muestre las que no están en esta lista

SELECT ciudad FROM ciudades
WHERE id_ciudad NOT IN (
select id_ciudad FROM ciudades_elegidas
)

Realmente sencillo a que sí. Por experiencia propia, realizar estos algoritmos en php (combinando arrays, crear arrays temporales…) es algo muy duro y que lleva bastante tiempo (sobre todo porque siempre falla algo) y eso que PHP tiene muy buenas funciones para manejar arrays.

Las subconsultas nos ayudan mucho, son muy útiles y potentes pero también muy costosas de ejecutar para mysql. Hay consultas que sin subconsultas serían imposibles pero siempre es mejor buscar otra alternativa (como JOIN por ejemplo) antes de “rendirte” y usar subselect. Por ejemplo, esta misma consulta de mostar las ciudades de la tabla ciudades_elegidas sería mucho mejor hacerla de esta manera

SELECT ciudad FROM ciudades_elegidas
JOIN ciudades USING (id_ciudad)

Pero sin embargo la consulta de mostrar las ciudades que no estan en la lista sería más dificililla y quizá la opción sí sería una subconsulta. Las capacidades de MySQL están ahí, luego depende de estos detalles el que una base de datos funcione más rápida que otras.

De las subconsultas (o subselect) no hay mucho más que decir, solo que tener cuidado (desde el punto de vista de la eficiencia) con ellas a la hora de usar tablas con muchas filas. En estos ejemplos no se aprecia, apenas tenemos filas pero créeme cuando te digo que he visto consultas casi 20 veces más rápidas usando JOIN en vez de subconsulta. Y como siempre, tabular para ayudar a quién lee la consulta. Aquí he usado subcosultas sencillas pero cuando tengas consultas de 15 líneas ya me dirás tu como lo agradable que sería verla en una sola línea.

Conclusión final, usa las subconsultas cuando no tengas otro remedio.

You may also like...

1 Response

  1. Elena Sánchez Mendívil dice:

    Hola, que claro eres Wow, ¿porque harán complicadas las explicaciones verdad? Si así fueran los maestros, que amena y clara y sencilla manera tienes de explicar las cosas, felicitaciones, además el background de Tu página cuida nuestros ojitos.
    Saludos y gracias por compartir 😀

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *