Sesion 4
Sesion 4
Sesion 4
SESION 4
Hemos visto los operadores relacionales: = (igual), <> (distinto), > (mayor), < (menor), >=
(mayor o igual), <= (menor o igual), is null/is not null (si un valor es NULL o no).
Hasta ahora, para recuperar de la tabla "libros" los libros con precio mayor o igual a 20 y
menor o igual a 40, usamos 2 condiciones unidas por el operador lógico "and":
select *from libros
where precio>=20 and
precio<=40;
Averiguamos si el valor de un campo dado (precio) está entre los valores mínimo y máximo
especificados (20 y 40 respectivamente).
Siempre que sea posible, emplee condiciones de búsqueda positivas ("between"), evite las
negativas ("not between") porque hace más lenta la recuperación de los datos.
Entonces, se puede usar el operador "between" para reducir las condiciones "where".
Problema:
Creamos la tabla:
Para seleccionar los libros cuyo precio NO esté entre un intervalo de valores antecedemos "not" al
"between":
Se utiliza "in" para averiguar si el valor de un campo está incluido en una lista de valores
especificada.
En la siguiente sentencia usamos "in" para averiguar si el valor del campo autor está incluido
en la lista de valores especificada (en este caso, 2 cadenas).
Hasta ahora, para recuperar los libros cuyo autor sea 'Paenza' o 'Borges' usábamos 2
condiciones:
select *from libros
where autor='Borges' or autor='Paenza';
Para recuperar los libros cuyo autor no sea 'Paenza' ni 'Borges' usábamos:
select *from libros
where autor<>'Borges' and
autor<>'Paenza';
Empleando "in" averiguamos si el valor del campo está incluido en la lista de valores
especificada; con "not" antecediendo la condición, invertimos el resultado, es decir,
recuperamos los valores que no se encuentran (coindicen) con la lista de valores.
Recuerde: siempre que sea posible, emplee condiciones de búsqueda positivas ("in"), evite las
negativas ("not in") porque con ellas se evalún todos los registros y esto hace más lenta la
recuperación de los datos.
Problema:
Creamos la tabla:
Hemos realizado consultas utilizando operadores relacionales para comparar cadenas. Por
ejemplo, sabemos recuperar los libros cuyo autor sea igual a la cadena "Borges":
select *from libros
where autor='Borges';
El operador igual ("=") nos permite comparar cadenas de caracteres, pero al realizar la
comparación, busca coincidencias de cadenas completas, realiza una búsqueda exacta.
sólo aparecerá el primer registro, ya que la cadena "Borges" no es igual a la cadena "J.L.
Borges".
Esto sucede porque el operador "=" (igual), también el operador "<>" (distinto) comparan
cadenas de caracteres completas. Para comparar porciones de cadenas utilizamos los
operadores "like" y "not like".
Entonces, podemos comparar trozos de cadenas de caracteres para realizar consultas. Para
recuperar todos los registros cuyo autor contenga la cadena "Borges" debemos tipear:
select *from libros
where autor like "%Borges%";
El símbolo "%" (porcentaje) reemplaza cualquier cantidad de caracteres (incluyendo ningún
caracter). Es un caracter comodín. "like" y "not like" son operadores de comparación que
señalan igualdad o diferencia.
Note que el símbolo "%" ya no está al comienzo, con esto indicamos que el título debe tener
como primera letra la "M" y luego, cualquier cantidad de caracteres.
Así como "%" reemplaza cualquier cantidad de caracteres, el guión bajo "_" reemplaza un
caracter, es otro caracter comodín. Por ejemplo, queremos ver los libros de "Lewis Carroll"
pero no recordamos si se escribe "Carroll" o "Carrolt", entonces tipeamos esta condición:
select *from libros
where autor like "%Carrol_";
Ejemplos:
... like '[a-cf-i]%': busca cadenas que comiencen con a,b,c,f,g,h o i;
... like '[-acfi]%': busca cadenas que comiencen con -,a,c,f o i;
... like 'A[_]9%': busca cadenas que comiencen con 'A_9';
... like 'A[nm]%': busca cadenas que comiencen con 'An' o 'Am'.
Para seleccionar los libros cuya editorial NO comienza con las letras "P" ni "N" tipeamos:
select titulo,autor,editorial
from libros
where editorial like '[^PN]%';
"like" se emplea con tipos de datos char, nchar, varchar, nvarchar o datetime. Si empleamos
"like" con tipos de datos que no son caracteres, SQL Server convierte (si es posible) el tipo de
dato a caracter. Por ejemplo, queremos buscar todos los libros cuyo precio se encuentre entre
10.00 y 19.99:
select titulo,precio from libros
where precio like '1_.%';
Para búsquedas de caracteres comodines como literales, debe incluirlo dentro de corchetes,
por ejemplo, si busca:
... like '%[%]%': busca cadenas que contengan el signo '%';
... like '%[_]%': busca cadenas que contengan el signo '_';
... like '%[[]%': busca cadenas que contengan el signo '[';
Problema:
Creamos la tabla:
Recuperamos todos los libros que contengan en el campo "autor" la cadena "Borges":
Si queremos ver los libros de "Lewis Carroll" pero no recordamos si se escribe "Carroll" o "Carrolt", podemos
emplear el comodín "_" (guión bajo) y establecer la siguiente condición:
Buscamos los libros cuya editorial comienza con las letras entre la "P" y la "S":
select titulo,autor,editorial
from libros
where editorial like '[P-S]%';
Seleccionamos los libros cuya editorial NO comienza con las letras "P" ni "N":
select titulo,autor,editorial
from libros
where editorial like '[^PN]%';
Recuperamos todos los libros cuyo precio se encuentra entre 10.00 y 19.99:
Existen en SQL Server funciones que nos permiten contar registros, calcular sumas,
promedios, obtener valores máximos y mínimos. Estas funciones se denominan funciones de
agregado y operan sobre un conjunto de valores (registros), no con datos individuales y
devuelven un único valor.
Imaginemos que nuestra tabla "libros" contiene muchos registros. Para averiguar la cantidad
sin necesidad de contarlos manualmente usamos la función "count()":
select count(*)
from libros;
La función "count()" cuenta la cantidad de registros de una tabla, incluyendo los que tienen
valor nulo.
También podemos utilizar esta función junto con la cláusula "where" para una consulta más
específica. Queremos saber la cantidad de libros de la editorial "Planeta":
select count(*)
from libros
where editorial='Planeta';
Para contar los registros que tienen precio (sin tener en cuenta los que tienen valor nulo),
usamos la función "count()" y en los paréntesis colocamos el nombre del campo que
necesitamos contar:
select count(precio)
from libros;
Note que "count(*)" retorna la cantidad de registros de una tabla (incluyendo los que tienen
valor "null") mientras que "count(precio)" retorna la cantidad de registros en los cuales el
campo "precio" no es nulo. No es lo mismo. "count(*)" cuenta registros, si en lugar de un
asterisco colocamos como argumento el nombre de un campo, se contabilizan los registros
cuyo valor en ese campo NO es nulo.
Problema:
Creamos la tabla:
select count(*)
from libros;
Note que incluye todos los libros aunque tengan valor nulo en algún campo.
select count(*)
from libros
where editorial='Planeta';
Contamos los registros que tienen precio (sin tener en cuenta los que tienen valor nulo), usando la función
"count(precio)":
select count(precio)
from libros;
"count_big(*)" cuenta la cantidad de registros de una tabla, incluyendo los valores nulos y
duplicados.
Note que incluye todos los libros aunque tengan valor nulo en algún campo.
Contamos los registros que tienen precio (sin tener en cuenta los que tienen valor nulo):
select count_big(precio)
from libros;
Problema:
Trabajamos con la tabla "libros" de una librería.
Eliminamos la tabla si existe:
Creamos la tabla:
select count_big(*)
from libros;
Note que incluye todos los libros aunque tengan valor nulo en algún campo.
select count_big(*)
from libros
where editorial='Planeta';
select count_big(precio)
from libros;
Hemos visto que SQL Server tiene funciones que nos permiten contar registros, calcular
sumas, promedios, obtener valores máximos y mínimos, las funciones de agregado.
Se pueden usar en una instrucción "select" y combinarlas con la cláusula "group by".
Todas estas funciones retornan "null" si ningún registro cumple con la condición del "where",
excepto "count" que en tal caso retorna cero.
El tipo de dato del campo determina las funciones que se pueden emplear con ellas.
Las relaciones entre las funciones de agrupamiento y los tipos de datos es la siguiente:
- count: se puede emplear con cualquier tipo de dato.
- min y max: con cualquier tipo de dato.
- sum y avg: sólo en campos de tipo numérico.
La función "sum()" retorna la suma de los valores que contiene el campo especificado. Si
queremos saber la cantidad total de libros que tenemos disponibles para la venta, debemos
sumar todos los valores del campo "cantidad":
select sum(cantidad)
from libros;
Para averiguar el valor máximo o mínimo de un campo usamos las funciones "max()" y "min()"
respectivamente.
Entonces, dentro del paréntesis de la función colocamos el nombre del campo del cuál
queremos el máximo valor.
La función "avg()" retorna el valor promedio de los valores del campo especificado. Queremos
saber el promedio del precio de los libros referentes a "PHP":
select avg(precio)
from libros
where titulo like '%PHP%';
Si realiza una consulta con la función "count" de un campo que contiene 18 registros, 2 de los
cuales contienen valor nulo, el resultado devuelve un total de 16 filas porque no considera
aquellos con valor nulo.
Todas las funciones de agregado, excepto "count(*)", excluye los valores nulos de los campos.
"count(*)" cuenta todos los registros, incluidos los que contienen "null".
Problema:
Creamos la tabla:
Para conocer la cantidad total de libros, sumamos las cantidades de cada uno:
select sum(cantidad)
from libros;
Retorna 980; verifique la suma, sumando los valores de todos los registros del campo "cantidad".
select sum(cantidad)
from libros
where editorial='Emece';
retorna 300.
select max(precio)
from libros;
retorna 46.00.
select min(precio)
from libros
where autor like '%Rowling%';
retorna 45.00.
select avg(precio)
from libros
where titulo like '%PHP%';
Devuelve 25.00. Note que hay 3 libros sobre "PHP", pero uno de ellos tiene precio nulo entonces SQL
Server no lo incluye para calcular el promedio.
Hemos aprendido que las funciones de agregado permiten realizar varios cálculos operando
con conjuntos de registros.
Las funciones de agregado solas producen un valor de resumen para todos los registros de un
campo. Podemos generar valores de resumen para un solo campo, combinando las funciones
de agregado con la cláusula "group by", que agrupa registros para consultas detalladas.
Queremos saber la cantidad de libros de cada editorial, podemos tipear la siguiente sentencia:
select count(*) from libros
where editorial='Planeta';
Entonces, para saber la cantidad de libros que tenemos de cada editorial, utilizamos la función
"count()", agregamos "group by" (que agrupa registros) y el campo por el que deseamos que
se realice el agrupamiento, también colocamos el nombre del campo a recuperar; la sintaxis
básica es la siguiente:
select CAMPO, FUNCIONDEAGREGADO
from NOMBRETABLA
group by CAMPO;
También se puede agrupar por más de un campo, en tal caso, luego del "group by" se listan
los campos, separados por comas. Todos los campos que se especifican en la cláusula "group
by" deben estar en la lista de selección.
select CAMPO1, CAMPO2, FUNCIONDEAGREGADO
from NOMBRETABLA
group by CAMPO1,CAMPO2;
Para obtener la cantidad libros con precio no nulo, de cada editorial utilizamos la función
"count()" enviándole como argumento el campo "precio", agregamos "group by" y el campo
por el que deseamos que se realice el agrupamiento (editorial):
select editorial, count(precio)
from libros
group by editorial;
Como resultado aparecen los nombres de las editoriales y la cantidad de registros de cada una,
sin contar los que tienen precio nulo.
Recuerde la diferencia de los valores que retorna la función "count()" cuando enviamos como
argumento un asterisco o el nombre de un campo: en el primer caso cuenta todos los registros
incluyendo los que tienen valor nulo, en el segundo, los registros en los cuales el campo
especificado es no nulo.
Para conocer el total en dinero de los libros agrupados por editorial:
select editorial, sum(precio)
from libros
group by editorial;
Para saber el máximo y mínimo valor de los libros agrupados por editorial:
select editorial,
max(precio) as mayor,
min(precio) as menor
from libros
group by editorial;
Para calcular el promedio del valor de los libros agrupados por editorial:
select editorial, avg(precio)
from libros
group by editorial;
Si incluye una cláusula "where", sólo se agrupan los registros que cumplen las condiciones.
Vamos a contar y agrupar por editorial considerando solamente los libros cuyo precio sea
menor a 30 pesos:
select editorial, count(*)
from libros
where precio<30
group by editorial;
Note que las editoriales que no tienen libros que cumplan la condición, no aparecen en la
salida. Para que aparezcan todos los valores de editorial, incluso los que devuelven cero o
"null" en la columna de agregado, debemos emplear la palabra clave "all" al lado de "group
by":
select editorial, count(*)
from libros
where precio<30
group by all editorial;
Entonces, usamos "group by" para organizar registros en grupos y obtener un resumen de
dichos grupos. SQL Server produce una columna de valores por cada grupo, devolviendo filas
por cada grupo especificado.
Problema:
Creamos la tabla:
Queremos saber la cantidad de libros de cada editorial, utilizando la cláusula "group by":
El resultado muestra los nombres de las editoriales y la cantidad de registros para cada valor del campo.
Note que los valores nulos se procesan como otro grupo.
La salida muestra los nombres de las editoriales y la cantidad de registros de cada una, sin contar los que
tienen precio nulo.
Para conocer el total en dinero de los libros agrupados por editorial, tipeamos:
Obtenemos el máximo y mínimo valor de los libros agrupados por editorial, en una sola sentencia:
select editorial,
max(precio) as mayor,
min(precio) as menor
from libros
group by editorial;
Es posible limitar la consulta con "where". Vamos a contar y agrupar por editorial considerando solamente
los libros cuyo precio es menor a 30 pesos:
Note que las editoriales que no tienen libros que cumplan la condición, no aparecen en la salida. Para que
aparezcan todos los valores de editorial, incluso los que devuelven cero o "null" en la columna de
agregado, debemos emplear la palabra clave "all" al lado de "group by":
Si queremos saber la cantidad de libros agrupados por editorial usamos la siguiente instrucción
ya aprendida:
select editorial, count(*)
from libros
group by editorial;
Si queremos saber la cantidad de libros agrupados por editorial pero considerando sólo algunos
grupos, por ejemplo, los que devuelvan un valor mayor a 2, usamos la siguiente instrucción:
select editorial, count(*) from libros
group by editorial
having count(*)>2;
En algunos casos es posible confundir las cláusulas "where" y "having". Queremos contar los
registros agrupados por editorial sin tener en cuenta a la editorial "Planeta".
Ambas devuelven el mismo resultado, pero son diferentes. La primera, selecciona todos los
registros rechazando los de editorial "Planeta" y luego los agrupa para contarlos. La segunda,
selecciona todos los registros, los agrupa para contarlos y finalmente rechaza fila con la cuenta
correspondiente a la editorial "Planeta".
Veamos otros ejemplos combinando "where" y "having". Queremos la cantidad de libros, sin
considerar los que tienen precio nulo, agrupados por editorial, sin considerar la editorial
"Planeta":
select editorial, count(*) from libros
where precio is not null
group by editorial
having editorial<>'Planeta';
Aquí, selecciona los registros rechazando los que no cumplan con la condición dada en
"where", luego los agrupa por "editorial" y finalmente rechaza los grupos que no cumplan con
la condición dada en el "having".
En una cláusula "having" puede haber hasta 128 condiciones. Cuando utilice varias
condiciones, tiene que combinarlas con operadores lógicos (and, or, not).
Podemos encontrar el mayor valor de los libros agrupados y ordenados por editorial y
seleccionar las filas que tengan un valor menor a 100 y mayor a 30:
select editorial, max(precio) as 'mayor'
from libros
group by editorial
having min(precio)<100 and
min(precio)>30
order by editorial;
Entonces, usamos la claúsula "having" para restringir las filas que devuelve una salida "group
by". Va siempre después de la cláusula "group by" y antes de la cláusula "order by" si la
hubiere.
Problema:
Creamos la tabla:
create table libros(
codigo int identity,
titulo varchar(40),
autor varchar(30),
editorial varchar(15),
precio decimal(5,2),
cantidad tinyint,
primary key(codigo)
);
Queremos saber la cantidad de libros agrupados por editorial pero considerando sólo algunos grupos, por
ejemplo, los que devuelvan un valor mayor a 2, usamos la siguiente instrucción:
Queremos el promedio de los precios de los libros agrupados por editorial, pero solamente de aquellos
grupos cuyo promedio supere los 25 pesos:
Queremos la cantidad de libros, sin considerar los que tienen precio nulo (where), agrupados por editorial
(group by), sin considerar la editorial "Planeta" (having):
Necesitamos el promedio de los precios agrupados por editorial, de aquellas editoriales que tienen más de
2 libros:
select editorial, avg(precio) from libros
group by editorial
having count(*) > 2;
Buscamos el mayor valor de los libros agrupados y ordenados por editorial y seleccionamos las filas que
tienen un valor menor a 100 y mayor a 30:
Podemos combinar "group by" con los operadores "rollup" y "cube" para generar valores de
resumen a la salida.
Tenemos la tabla "visitantes" con los siguientes campos: nombre, edad, sexo, domicilio,
ciudad, telefono, montocompra.
Esta consulta muestra el total de visitantes agrupados por ciudad; pero si queremos además la
cantidad total de visitantes, debemos realizar otra consulta:
select count(*) as total
from visitantes;
Para obtener ambos resultados en una sola consulta podemos usar "with rollup" que nos
devolverá ambas salidas en una sola consulta:
select ciudad,count(*) as cantidad
from visitantes
group by ciudad with rollup;
La consulta anterior retorna los registros agrupados por ciudad y una fila extra en la que la
primera columna contiene "null" y la columna con la cantidad muestra la cantidad total.
La cláusula "group by" permite agregar el modificador "with rollup", el cual agrega registros
extras al resultado de una consulta, que muestran operaciones de resumen.
La salida muestra los totales por ciudad y sexo y produce tantas filas extras como valores
existen del primer campo por el que se agrupa ("ciudad" en este caso), mostrando los totales
para cada valor, con la columna correspondiente al segundo campo por el que se agrupa
("sexo" en este ejemplo) conteniendo "null", y 1 fila extra mostrando el total de todos los
visitantes (con las columnas correspondientes a ambos campos conteniendo "null"). Es decir,
por cada agrupación, aparece una fila extra con el/ los campos que no se consideran, seteados
a "null".
Entonces, "rollup" es un modificador para "group by" que agrega filas extras mostrando
resultados de resumen de los subgrupos. Si se agrupa por 2 campos SQL Server genera tantas
filas extras como valores existen del primer campo (con el segundo campo seteado a "null") y
una fila extra con ambos campos conteniendo "null".
Con "rollup" se puede emplear "where" y "having", pero no es compatible con "all".
Problema:
Un comercio que tiene un stand en una feria registra en una tabla llamada "visitantes" algunos datos de las
personas que visitan o compran en su stand para luego enviarle publicidad de sus productos.
Necesitamos la cantidad de visitantes por ciudad y el total de visitantes. Para obtener ambos resultados
en una sola consulta empleamos "with rollup":
select ciudad,
count(*) as cantidad
from visitantes
group by ciudad with rollup;
La consulta anterior retorna los registros agrupados por ciudad y una fila extra (la cuarta) en la que la
primera columna contiene "null" y la columna con la cantidad muestra la cantidad total.
Veamos las filas de resumen cuando agrupamos por 2 campos, "ciudad" y "sexo":
select ciudad,sexo,
count(*) as cantidad
from visitantes
group by ciudad,sexo
with rollup;
La salida muestra los totales por ciudad y sexo (5 filas) y produce 4 filas extras, 3 muestran los totales
para cada ciudad (con la columna correspondiente al sexo conteniendo "null") y 1 mostrando el total de
todos los visitantes (con las columnas correspondientes a la ciudad y al sexo conteniendo "null").
Podemos incluir varias funciones de agrupamiento; para conocer la cantidad de visitantes y la suma de sus
compras agrupados por ciudad y sexo, tipeamos:
select ciudad,sexo,
count(*) as cantidad,
sum(montocompra) as total
from visitantes
group by ciudad,sexo
with rollup;
Note que por cada agrupación aparece una fila extra con valores de resumen.
Hemos aprendido el modificador "rollup", que agrega filas extras mostrando resultados de
resumen por cada grupo y subgrupo.
Por ejemplo, tenemos una tabla llamada "empleados" que contiene, entre otros, los campos
"sexo", "estadocivil" y "seccion".
Si se agrupa por esos tres campos (en ese orden) y se emplea "rollup":
select sexo,estadocivil,seccion,
count(*) from empleados
group by sexo,estadocivil,seccion
with rollup;
SQL Server genera varias filas extras con información de resumen para los siguientes
subgrupos:
- sexo y estadocivil (seccion seteado a "null"),
- sexo (estadocivil y seccion seteados a "null") y
- total (todos los campos seteados a "null").
Si se emplea "cube":
select sexo,estadocivil,seccion,
count(*) from empleados
group by sexo,estadocivil,seccion
with cube;
Es decir, "cube" genera filas de resumen de subgrupos para todas las combinaciones posibles
de los valores de los campos por los que agrupamos.
Con "cube" se puede emplear "where" y "having", pero no es compatible con "all".
Problema:
Una empresa tiene registrados sus empleados en una tabla llamada "empleados".
Elimine la tabla si existe:
select sexo,estadocivil,seccion,
count(*) from empleados
group by sexo,estadocivil,seccion
with rollup;
SQL Server genera varias filas extras con información de resumen para los siguientes subgrupos:
Si empleamos "cube":
select sexo,estadocivil,seccion,
count(*) from empleados
group by sexo,estadocivil,seccion
with cube;