Conoce SQL – SELECT – Parte 1

Conoce SQL – DQL – Parte 1

Todo lo visto hasta ahora entra en la parte DDL (Lenguaje de Definición de Datos). Esa parte es las más sencillita. Ahora comenzamos con el DQL (Lenguaje de Consulta de Datos). DQL es sin duda la parte más compleja y divertida de SQL y es la que nos permite sacar datos de la base de datos.

Normalmente en los ejemplos que se ven por ahí se usan consultas sencillas del tipo

SELECT * FROM usuarios WHERE email=’[email protected]

y rara vez he visto una consulta juntandos varias tablas o usando funciones de MySQL, algo que esconde totalmente la potencia de este lenguaje.

Antes de comenzar quiero aclarar ciertos detalles:
En SQL estandar para escribir una cadena de texto se usan comillas simples y no dobles. A pesar de esto, mysql nos deja usar comillas dobles también pero cuidado porque otros SGDB son más estrictos y por ejemplo Oracle te daría error si usas comillas dobles.
SQL no es case-sensitve (salvo en los datos evidentemente), esto quiere decir que da igual que pongamos “SELECT *…” que “SeLeCT *”. Pero una norma no escrita dice que para las palabras reservadas del lenguaje usemos mayúsculas y para las nuestras usar minusculas. Un ejemplo seria la consulta que puse de ejemplo antes donde ves que SELECT, FROM, WHERE estan en mayusculas pero usuarios, email estan en minusculas. Esto ayuda bastante a leer consultas.

También es importante tabular, como en cualquier lenguaje. Aunque lo normal es ver selects sencillos de una sola línea, nos daremos cuenta de que es mucho más potente, práctico y eficiente realizar consultas más complejas. Que no te asuste esto de consultas complejas, es mucho más sencillo que usar varios arrays y luego unirlos y… buf que me mareo.

Anteriormente hablé de las FOREIGN KEY y ahora es cuando vamos a ver lo útiles que no son. Supongamos que tenemos la tabla paquetes y ciudades creadas en dicho capítulo. Queremos simplemente una consulta que devuelva el código del paquete, la descripción y el nombre de la ciudad. En la tabla paquetes lo que guardabámos era la referencia a la ciudad así que tenemos que unir las dos tablas. Para ello vamos a usar JOIN

Antes de nada, vamos a insertar datos. Ahora solo pongo las consultas para insertar, más adelante hablaré de ellas
Ciudades:

INSERT INTO ciudades (id_ciudad,ciudad) VALUES (0,’Palencia’),(1,’Valladolid’),(2,’Madrid’)

Aquí lo suyo hubiera sido poner a id_ciudad como auto increment pero bueno

INSERT INTO paquetes (codigo_paquete,descripcion,id_ciudad) VALUES (‘PA123′,’Paquete cuadrado’,0),(‘PA124′,’Muy bonito’,0),(‘MA125′,’Es amarillo’,2),(‘VA126′,’Suena a roto’,1),(‘VA127′,’Pesa mucho’,1),(‘PA125′,’Este no’,0),(‘VA128′,’Es grande’,1),(‘PA129′,’También este’,0)

Los paquetes y sus destinos.

Para hacer luego una consulta mas bonita vamos a añadir la columna fecha_entrega y que por defecto sea nulo

ALTER TABLE paquetes ADD fecha_entrega DATE NULL

Y hacemos que algun paquete haya sido entregado

UPDATE paquetes SET fecha_entrega = ‘2009-04-22′ WHERE codigo_paquete=’MA125’;
UPDATE paquetes SET fecha_entrega = ‘2009-01-23′ WHERE codigo_paquete=’VA126’;

Aquí podríamos poner un trigger para evitar que se ponga como fecha de entrega una fecha del futuro, ya veremos como. Y por último vamos a insertar una ruta, la del paquete PA123 que debe estar apunto de llegar a su destino.

INSERT INTO ciudades_paquetes (codigo_paquete,id_ciudad,fecha) VALUES (‘PA123′,2,’02-02-2002’),(‘PA123′,1,’03-02-2002’)

El destino de este paquete es Palencia y ha pasado por Madrid y Valladolid asi que en breve espero que me llegue 😛

Existen varios tipos de JOIN, en la documentación de mysql hay una extensa explicación asi que yo solo me limitaré a explicar los usos mas frecuentes:

NATURAL JOIN tabla -> Une las dos tablas usando como relación la clave primaria de la tabla unida. En la tabla “original” tiene que haber una columna conel mismo nombre y tipo de dato. Además no tiene que haber ningúna otra columna con el mismo nombre. Esto es porque une las dos tablas y no se puede dar el caso de que en la union de dos tablas haya dos columnas iguales en la resultante. En nuestro caso seria:

SELECT codigo_paquete,descripcion,ciudad FROM paquetes
NATURAL JOIN ciudades

Natural join es la forma más eficiente de unir tablas así que siempre que podamos es conveniente usarla. Para hacer un diseño donde sea fácil usar natural join tenemos que tener en cuenta principalmente:

  • No haya columnas con los mismos nombres en ninguna de las tablas que vayamos a unir
  • En la tablas, las columna que usemos para realizar esta unión se llamen igual

Natural join está muy bien pero ojo cuando unas muchas tablas, a veces se hace la picha un lío así que cuidado y asegúrate en esos casos de que los datos mostrados son correctos.

JOIN tabla USING (columna) -> Igual que natural join pero esta si permite que haya columnas con nombres duplicados. En este join hay que especificar el campo que se usa para realizar la unión. Para diferenciar una columna con nombre repetido de otra se hace de esta manera:

SELECT codigo_paquete,descripcion,ciudad FROM paquetes
JOIN ciudades USING (id_ciudad)

Obervamos que el resultado es exactamente el mismo. Si hubiera algun campo duplicado la solución es sencilla:

SELECT paquetes.codigo_paquete,paquetes.descripcion,ciudades.ciudad FROM paquetes
JOIN ciudades USING (id_ciudad)

Como ves solo hay que indicar la tabla a la que estamos refiriéndonos y hay otra manera que es usando alias:

SELECT p.codigo_paquete,p.descripcion,c.ciudad FROM paquetes p
JOIN ciudades c USING (id_ciudad)

Un alias es un nombre alternativo que le damos a una tabla. Es válido solo en esa consulta y se especifica justo despues de la tabla. En este caso el alias de paquetes es p (puede ser la palabra que queramos) y el de ciudad es c. La utilidad de esto es que cuando tenemos muchos campos pues nos ahorramos escribir bastante

JOIN tabla ON (columna1=columna2) -> Hace lo mismo pero cuando las columnas de union se llaman diferentes. También para cuando queremos unir por varios elementos por ejemplo JOIN tabla ON (columna1=columna2 AND columna3=columna5) y todo lo complejo que queramos. Normalmente en este join se usan los cualificadores (lo de paquetes.codigo por ejemplo).

LEFT | RIGHT JOIN tabla USING | ON … -> Simplemente poner LEFT o RIGTH delante del JOIN USING o JOIN ON. Esto sirve para que, por ejemplo, en una union el campo es nulo con un join normal no se realiza la unión. Una mala expliación pero vamos con un ejemplo:

SELECT codigo_paquete,descripcion,ciudad FROM paquetes
JOIN ciudades_paquetes cp USING (codigo_paquete)
JOIN ciudades c ON (cp.id_ciudad=c.id_ciudad)

Esta consulta nos mostrará todas las rutas pero si algún paquete no ha comenzado la ruta ahi NO aparecera porque no hay datos que relacionen un paquete con ninguna fila en la otra tabla. Pero si lo que queremos es que nos aparezca todas las filas necesitamos usar LEFT

SELECT codigo_paquete,descripcion,ciudad FROM paquetes
LEFT JOIN ciudades_paquetes cp USING (codigo_paquete)
LEFT JOIN ciudades c ON (cp.id_ciudad=c.id_ciudad)

De esta manera nos apareceran todas las filas y los que sean nulos pues nos da valor NULL. Los LEFT y RIGHT son las complicadillos de usar y muchas veces se hacen algoritmos muy duros cuando con un simple LEFT join se soluciona.

Ahora que ya sabemos usar los JOIN vamos a meter alguna función para que nos quede más bonito. Ahora vamos a presentar los datos de manera más bonita que con un simple NULL. En el primer capítulo dije que los NULOS son algo imporante y ahora vamos a ver otra utilidad de estos nulo.

SELECT codigo_paquete,descripcion,IFNULL(ciudad,’No se inicio ruta’) as ciudad FROM paquetes
LEFT JOIN ciudades_paquetes cp USING (codigo_paquete)
LEFT JOIN ciudades c ON (cp.id_ciudad=c.id_ciudad)

Ahora en vez de null nos mostrará “No se inició ruta”. La función IFNULL es igual que NVL de oracle (por si alguien conocía la otra). Valida el primer dato que le pasamos a la función y si es nulo, nos lo cambia. Ves que he puesto despudes de la funcion “as ciudad”. Eso tambiés es un alias. Es recomendable usarlo, así luego desde php podremos acceder a ese valor desde $fila[‘cuidad’] cosa que si usar un alias de ese campo no podríamos acceder a menos que usemos índices numéricos $fila[2] en este caso.

Además poner alias cuando usemos una función es obligatorio en la vistas, eso ya lo veremos otro día.

Otra utilidad sería para saber los paquetes entregados

SELECT codigo_paquete,descripcion,ciudad,IFNULL(fecha_entrega,’No entregado’) as entregado FROM paquetes
JOIN ciudades USING (id_ciudad)

Así luego desde PHP no tenemos que hacer

if($fila[‘fecha_entrega’]=””) $fila [‘fecha_entrega’]=”No entregado”;

Recuerda que todo lo que podamos hacer desde el Sistema Gestor de Bases de Datos es mejor que hacerlo desde PHP. Digo que es mejor porque es mucho más práctico y en muchos casos más eficiente (como siempre digo :P)

Ahora lo que puedes hacer es ir practicando con los JOIN y ver por ti mismo las diferencias. Otro dia continúo con ordernar datos, agrupaciones y otros temas de ese tipo que por hoy ya es suficiente.

Nos vemos

    You may also like...

    Deja un comentario

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