Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
INNER JOIN
Inner join slo produce los registros que coinciden en las dos tablas A y B.
Cdigo (sql)
1. SELECT * FROM TablaA
2. INNER JOIN TablaB
3. ON TablaA.nombre = TablaB.nombre
Full outer join produce el conjunto de todos los registros en las tablas A y B, con registros
coincidentes en ambos lados cuando sea posible. Si no hay coincidencia, el lado que falta
contendr null.
Cdigo (sql)
1. SELECT * FROM TablaA
2. FULL OUTER JOIN TablaB
3. ON TablaA.nombre = TablaB.nombre
Left outer join produce el conjunto completo de registros de la tabla A, con los registros
coincidentes (si estn disponibles) en la tabla B. Si no hay coincidencia, el lado derecho
contendr null.
Cdigo (sql)
1. SELECT * FROM TablaA
2. LEFT OUTER JOIN TablaB
3. ON TablaA.nombre = TablaB.nombre
Tambin hay un cross join, el cul no puede ser expresado con un diagrama de Venn:
Cdigo (sql)
1. SELECT * FROM TablaA
2. CROSS JOIN TablaB
Esto une todo con todo, dando como resultado 4 x 4 = 16 filas, muchas ms de las que
tenamos en los conjuntos originales. Si haces unos simples clculos, puedes ver por qu
es un Join muy peligroso de ejecutar en tablas grandes.
UNION
El comando unin trabaja sobre los resultados de las consultas, nos sirve para unir las
columnas resultantes.
Cdigo (sql)
1. SELECT * FROM tablaA
2. WHERE tablaA.nombre = Juan
3. UNION
4. SELECT * FROM tablaB
5. WHERE tablaB.nombre = Juan
GROUP BY
La clusula GROUP BY en SQL permite realizar agrupaciones de registros de una tabla.
Examinemos la siguiente tabla que contiene datos de los empleados de una empresa.
Si en esta tabla deseramos calcular el salario medio de los empleados agrupados por
oficio, deberamos escribir una sentencia SQL que agrupara las filas con un mismo nombre
de oficio. De cada uno de los grupos que se formen se aplicara la funcin AVG sobre el
campo salario.
De la misma forma, si quisiramos contar el nmero de empleados de cada departamento
deberamos realizar un agrupamiento de los empleados por el campo departamento. De
cada uno de los grupos formados se aplicara la funcin COUNT.
La sintaxis bsica de la clusula GROUP BY en una sentencia SELECT es la siguiente:
1.
2.
3.
4.
5.
SELECT campos
FROM tablas
WHERE condiciones
GROUP BY campo1, campo2, campo3...
ORDER BY campo1, campo2, campo3...
La clusula GROUP BY siempre va detrs de la clusula WHERE (si es que la hay), y delante
siempre de ORDER BY (si es que realizamos la ordenacin de acuerdo un campo
determinado).
1. SELECT oficio, AVG(salario)
2. FROM emple
3. GROUP BY oficio;
Hemos empleado la clusula ORDER BY para mostrar el resultado ordenado por nmero
de departamento. La clusula GROUP BY DEPT_NO obliga a COUNT a contar las filas que
se han agrupado por cada departamento.
Veamos otro ejemplo ms. Queremos obtener por cada agrupamiento de departamento y
oficio el salario medio. Es decir, por cada departamento queremos calcular el salario
medio agrupado por oficio. En este caso debemos agrupar los registros por nmero de
departamento, y dentro de cada departamento por oficio.
1.
SELECT
dept_no,
oficio,
2. FROM emple GROUP BY dept_no,oficio;
AVG(salario)
En una sentencia SELECT pueden aparecer juntos tanto la clusula WHERE como la
clusula GROUP BY. Si quisiramos calcular, por ejemplo, el salario medio de cada
departamento sin tener en cuenta aquellos empleados que cobren menos de 1000 euros,
la sentencia correcta en SQL sera:
1.
2.
3.
4.
En este caso no se tiene en cuenta el empleado 1005 para realizar la media de salarios.
HAVING
La clusula HAVING permite especificar condiciones a los agrupamientos realizados con
GROUP BY. Del mismo modo que existe la clusula WHERE para filas individuales en la
sentencia SELECT, tambin se puede especificar una condicin para grupos de registros. Al
utilizar la clusula HAVING no se incluyen aquellos grupos que no cumplan una
determinada condicin.
La clusula HAVING siempre va detrs de la clusula GROUP BY y no puede existir sin sta.
Si queremos visualizar, por ejemplo, el salario medio de cada departamento pero slo de
aquellos cuyo salario medio sea mayor de 1200, la sentencia en SQL sera:
1.
2.
3.
4.
Si, por ejemplo, queremos obtener el nmero de empleados de cada departamento pero
slo de aquellos que tengan ms de 2 empleados, la manera correcta sera:
1.
2.
3.
4.
SELECT dept_no,COUNT(*)
FROM emple
GROUP BY dept_no
HAVING COUNT(*)>2;
SELECT dept_no,COUNT(*)
FROM emple
GROUP BY dept_no
HAVING COUNT(*)>2
ORDER BY COUNT(*) DESC;
SENTENCIAS ANIDADAS
La gerencia te pide que expongas en un reporte un resumen de las compras y ventas de
los artculos en el ltimo mes, donde compares lado a lado, cuantos se vendieron, cuantos
se compraron por artculo, quedando quizs algo por el estilo:
Camisa
XXX
XXX
002
Pantalon
XXX
XXX
003
Blusa
XXX
XXX
Parece algo sencillo y no muy difcil de realizar, pero es tpico que en el diseo de tu base
de datos hayas dejado por separado una entidad para compras y una entidad para ventas,
por lo que tendramos los siguientes entidades:
Lo primero que se nos podra ocurrir es una consulta donde proyectramos "todos" vs
"todos" para obtener conjunto de datos deseados:
1.
2.
3.
4.
5.
6.
7.
SELECT Ventas.IDArticulo,
SUM(compras.Cantidad) AS SumaCompras,
SUM(ventas.cantidad) AS SumaVentas
FROM Compras
FULL JOIN Ventas
ON Ventas.IdArticulo = Compras.IdArticulo
GROUP BY Ventas.idarticulo INTO CURSOR cResumen
A primera vista parece buena la idea, sumamos todas las cantidades de compras, todas las
cantidades de ventas de una mezcla de todos los registros, no? Pero sabrs que pasa?: No
funciona, ya que obtendremos datos que nada tienen que ver, primeramente porque se
estn cualificando las tuplas de la tabla ventas contra las tuplas de la tabla compras, pero
ntese que hay algunos IDs que estn en una, pero que no estn en la otra, dndonos el
siguiente resultado:
Podrs comentar, "Ya casi", solo me falt el cdigo 002 que es de la tabla compras que no
estaba en la tabla ventas, en efecto es as, puedes seguir intentando cambiar las clusulas
por LEFT JOIN, RIGTH JOIN, cambiar Ventas.Articulo = Compras.IdArticulo por
Compras.IdArticulo = Ventas.Articulo en lo correspondiente a la clusula ON (de los
operadores de proyeccin), pero obtendrs diferentes resultados que seguirn sin ser los
que esperabas.
Inclusive, puedes llegar a pensar que tal vez el operador de igualdad sale sobrando, e
intentas una ms para ver si funciona:
1.
2.
3.
4.
5.
6.
SELECT ventas.idArticulo,
SUM(ventas.cantidad) AS TotalVentas,
SUM(compras.cantidad) AS TotalCompras
FROM ventas,compras
GROUP BY ventas.idArticulo
INTO CURSOR cReporte
Resulta ser que el lgebra de conjunto (que es la teora que sustenta a la prctica de el
lenguaje SQL) tiene un pequeo "truco" para normalizar este pequeo desperfecto en lo
que parece no tener solucin. Esto se le llaman subconsultas (mas adelante veremos que
otros nombres se les conoce).
En el prrafo anterior se hace mencin a un tema que es base de esto, la normalizacin,
en vez de intentar proyectar las columnas que sern calculadas (en nuestro ejemplo se
sumaron, pero bien pudieron haber sido contadas) para llegar al resultado inmediato,
debemos crear un conjunto de datos intermedio, el cual, nos servir para ahora si
proyectarlo correctamente:
1.
2.
3.
4.
5.
6.
Con el query anterior obtendremos un conjunto de datos normalizados como el que sigue:
Aqu se har uso de lo que se le denomina sentencias anidadas, en donde tenemos varias
partes clave.
1.
2.
3.
4.
5.
6.
SELECT idArticulo,
SUM(nCompras) as TotalCompras ,
SUM(nVentas) as TotalVentas
FROM cResumen
GROUP BY idArticulo
INTO CURSOR cReporte