Sesion 4

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 22

SQL SERVER

SESION 4

1 - Otros operadores relacionales (between)

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).

Otro operador relacional es "between", trabajan con intervalos de valores.

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;

Podemos usar "between" y así simplificar la consulta:


select *from libros
where precio between 20 and 40;

Averiguamos si el valor de un campo dado (precio) está entre los valores mínimo y máximo
especificados (20 y 40 respectivamente).

"between" significa "entre". Trabaja con intervalo de valores.


Este operador se puede emplear con tipos de datos numéricos y money (en tales casos
incluyen los valores mínimo y máximo) y tipos de datos fecha y hora (incluye sólo el valor
mínimo).

No tiene en cuenta los valores "null".

Si agregamos el operador "not" antes de "between" el resultado se invierte, es decir, se


recuperan los registros que están fuera del intervalo especificado. Por ejemplo, recuperamos
los libros cuyo precio NO se encuentre entre 20 y 35, es decir, los menores a 15 y mayores a
25:
select *from libros
where precio not between 20 and 35;

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe:

if object_id ('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(20) default 'Desconocido',
editorial varchar(20),
precio decimal(6,2),
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Emece',15.90);
insert into libros
values('Cervantes y el quijote','Borges','Paidos',null);
insert into libros
values('Alicia en el pais de las maravillas','Lewis Carroll',null,19.90);
insert into libros
values('Martin Fierro','Jose Hernandez','Emece',25.90);
insert into libros (titulo,autor,precio)
values('Antología poética','Borges',32);
insert into libros (titulo,autor,precio)
values('Java en 10 minutos','Mario Molina',45.80);
insert into libros (titulo,autor,precio)
values('Martin Fierro','Jose Hernandez',40);
insert into libros (titulo,autor,precio)
values('Aprenda PHP','Mario Molina',56.50);

Recuperamos los registros cuyo precio esté entre 20 y 40 empleando "between":

select *from libros


where precio between 20 and 40;

Note que si el campo tiene el valor "null", no aparece en la selección.

Para seleccionar los libros cuyo precio NO esté entre un intervalo de valores antecedemos "not" al
"between":

select *from libros


where precio not between 20 and 35;

2 - Otros operadores relacionales (in)

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';

Podemos usar "in" y simplificar la consulta:


select *from libros
where autor in('Borges','Paenza');

Para recuperar los libros cuyo autor no sea 'Paenza' ni 'Borges' usábamos:
select *from libros
where autor<>'Borges' and
autor<>'Paenza';

También podemos usar "in" anteponiendo "not":


select *from libros
where autor not in ('Borges','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.

Los valores "null" no se consideran.

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe:

if object_id ('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(20),
editorial varchar(20),
precio decimal(6,2),
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Emece',15.90);
insert into libros
values('Cervantes y el quijote','Borges','Paidos',null);
insert into libros
values('Alicia en el pais de las maravillas','Lewis Carroll',null,19.90);
insert into libros
values('Matematica estas ahi','Paenza','Siglo XXI',15);
insert into libros (titulo,precio)
values('Antología poética',32);
insert into libros (titulo,autor,precio)
values('Martin Fierro','Jose Hernandez',40);
insert into libros (titulo,autor,precio)
values('Aprenda PHP','Mario Molina',56.50);

Recuperamos los libros cuyo autor es "Paenza" o "Borges":

select *from libros


where autor in('Borges','Paenza');

Recuperamos los libros cuyo autor NO es "Paenza" ni "Borges":

select *from libros


where autor not in ('Borges','Paenza');
Note que los valores "null" no se consideran.

3 - Búsqueda de patrones (like - not like)

Existe un operador relacional que se usa para realizar comparaciones exclusivamente de


cadenas, "like" y "not like".

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.

Imaginemos que tenemos registrados estos 2 libros:


"El Aleph", "Borges";
"Antologia poetica", "J.L. Borges";

Si queremos recuperar todos los libros de "Borges" y especificamos la siguiente condición:


select *from libros
where autor='Borges';

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.

Para seleccionar todos los libros que comiencen con "M":


select *from libros
where titulo like 'M%';

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.

Para seleccionar todos los libros que NO comiencen con "M":


select *from libros
where titulo not like 'M%';

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_";

Otro caracter comodín es [] reemplaza cualquier carácter contenido en el conjunto especificado


dentro de los corchetes.
Para seleccionar los libros cuya editorial comienza con las letras entre la "P" y la "S" usamos la
siguiente sintaxis:
select titulo,autor,editorial
from libros
where editorial like '[P-S]%';

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'.

El cuarto caracter comodín es [^] reemplaza cualquier caracter NO presente en el conjunto


especificado dentro de los corchetes.

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_.%';

Queremos los libros que NO incluyen centavos en sus precios:


select titulo,precio from libros
where precio like '%.00';

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe:

if object_id ('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(20) default 'Desconocido',
editorial varchar(20),
precio decimal(6,2),
primary key(codigo)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Emece',15.90);
insert into libros
values('Antología poética','J. L. Borges','Planeta',null);
insert into libros
values('Alicia en el pais de las maravillas','Lewis Carroll',null,19.90);
insert into libros
values('Matematica estas ahi','Paenza','Siglo XXI',15);
insert into libros
values('Martin Fierro','Jose Hernandez',default,40);
insert into libros
values('Aprenda PHP','Mario Molina','Nuevo siglo',56.50);

Recuperamos todos los libros que contengan en el campo "autor" la cadena "Borges":

select *from libros


where autor like '%Borges%';

Seleccionamos los libros cuyos títulos comienzan con la letra "M":

select *from libros


where titulo like 'M%';

Seleccionamos todos los títulos que NO comienzan con "M":

select *from libros


where titulo not like 'M%';

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:

select *from libros


where autor like '%Carrol_';

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:

select titulo,precio from libros


where precio like '1_.%';

Recuperamos los libros que NO incluyen centavos en sus precios:

select titulo,precio from libros


where precio like '%.00';

4 - Contar registros (count)

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe:

if object_id ('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(20) default 'Desconocido',
editorial varchar(20),
precio decimal(6,2),
primary key(codigo)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Emece',15.90);
insert into libros
values('Antología poética','J. L. Borges','Planeta',null);
insert into libros
values('Alicia en el pais de las maravillas','Lewis Carroll',null,19.90);
insert into libros
values('Matematica estas ahi','Paenza','Siglo XXI',15);
insert into libros
values('Martin Fierro','Jose Hernandez',default,40);
insert into libros
values('Aprenda PHP','Mario Molina','Nuevo siglo',null);
insert into libros
values('Uno','Richard Bach','Planeta',20);

Averiguemos la cantidad de libros usando la función "count()":

select count(*)
from libros;

Note que incluye todos los libros aunque tengan valor nulo en algún campo.

Contamos los libros de editorial "Planeta":

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;

5 - Contar registros (count_big)

Retorna la cantidad de registros. Es similar a la función "count(*)", la diferencia es que


"count_big" retorna un valor "bigint" y "count", un "int".

"count_big(*)" cuenta la cantidad de registros de una tabla, incluyendo los valores nulos y
duplicados.

"count_big(CAMPO)" retorna la cantidad de registros cuyo valor en el campo especificado entre


paréntesis no es nulo.

"count_big(distinct CAMPO)" retorna la cantidad de registros cuyo valor en el campo


especificado no es nulo, sin considerar los repetidos.

Averiguemos la cantidad de libros usando la función "count_big()":


select count_big(*)
from libros;

Note que incluye todos los libros aunque tengan valor nulo en algún campo.

Contamos los libros de editorial "Planeta":


select count_big(*)
from libros
where editorial='Planeta';

Contamos los registros que tienen precio (sin tener en cuenta los que tienen valor nulo):
select count_big(precio)
from libros;

Contamos las editoriales (sin repetir):


select count_big(distinct editorial)
from libros;

Problema:
Trabajamos con la tabla "libros" de una librería.
Eliminamos la tabla si existe:

if object_id ('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(20) default 'Desconocido',
editorial varchar(20),
precio decimal(6,2),
primary key(codigo)
);

Ingresamos algunos registros:

insert into libros values('El aleph','Borges','Emece',15.90);


insert into libros values('Antología poética','Borges','Planeta',null);
insert into libros values('Alicia en el pais de las maravillas','Lewis
Carroll',null,19.90);
insert into libros values('Matematica estas ahi','Paenza','Siglo XXI',15);
insert into libros values('Martin Fierro','Jose Hernandez',default,40);
insert into libros values('Aprenda PHP','Mario Molina','Nuevo siglo',null);
insert into libros values('Uno','Richard Bach','Planeta',20);

Contamos los libros usando "count_big()":

select count_big(*)
from libros;

Note que incluye todos los libros aunque tengan valor nulo en algún campo.

Contamos los libros de editorial "Planeta":

select count_big(*)
from libros
where editorial='Planeta';

Averiguamos la cantidad de libros que tienen precio:

select count_big(precio)
from libros;

Contamos las editoriales (sin repetir):

select count_big(distinct editorial)


from libros;

6 - Funciones de agrupamiento (count - sum - min - max - avg)

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.

Ya hemos aprendido una de ellas, "count()", veamos otras.

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.

Queremos saber cuál es el mayor precio de todos los libros:


select max(precio)
from libros;

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%';

Ahora podemos entender porque estas funciones se denominan "funciones de agrupamiento",


porque operan sobre conjuntos de registros, no con datos individuales.
Tratamiento de los valores nulos:

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(30) default 'Desconocido',
editorial varchar(15),
precio decimal(5,2),
cantidad tinyint,
primary key(codigo)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Planeta',15,null);
insert into libros
values('Martin Fierro','Jose Hernandez','Emece',22.20,200);
insert into libros
values('Antologia poetica','J.L. Borges','Planeta',null,150);
insert into libros
values('Aprenda PHP','Mario Molina','Emece',18.20,null);
insert into libros
values('Cervantes y el quijote','Bioy Casares- J.L.
Borges','Paidos',null,100);
insert into libros
values('Manual de PHP', 'J.C. Paez', 'Siglo XXI',31.80,120);
insert into libros
values('Harry Potter y la piedra filosofal','J.K. Rowling',default,45.00,90);
insert into libros
values('Harry Potter y la camara secreta','J.K. Rowling','Emece',46.00,100);
insert into libros (titulo,autor,cantidad)
values('Alicia en el pais de las maravillas','Lewis Carroll',220);
insert into libros (titulo,autor,cantidad)
values('PHP de la A a la Z',default,0);

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".

Queremos saber cuántos libros tenemos de la editorial "Emece":

select sum(cantidad)
from libros
where editorial='Emece';

retorna 300.

Queremos saber cuál es el libro más costoso; usamos la función "max()":

select max(precio)
from libros;

retorna 46.00.

Para conocer el precio mínimo de los libros de "Rowling" tipeamos:

select min(precio)
from libros
where autor like '%Rowling%';

retorna 45.00.

Queremos saber el promedio del precio de los libros referentes a "PHP":

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.

7 - Agrupar registros (group by)

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';

y repetirla con cada valor de "editorial":


select count(*) from libros
where editorial='Emece';
select count(*) from libros
where editorial='Paidos';
...

Pero hay otra manera, utilizando la cláusula "group by":


select editorial, count(*)
from libros
group by editorial;

La instrucción anterior solicita que muestre el nombre de la editorial y cuente la cantidad


agrupando los registros por el campo "editorial". Como resultado aparecen los nombres de las
editoriales y la cantidad de registros para cada valor del campo.

Los valores nulos se procesan como otro grupo.

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;

Es posible limitar la consulta con "where".

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

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)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Planeta',15,null);
insert into libros
values('Martin Fierro','Jose Hernandez','Emece',22.20,200);
insert into libros
values('Antologia poetica','J.L. Borges','Planeta',null,150);
insert into libros
values('Aprenda PHP','Mario Molina','Emece',18.20,null);
insert into libros
values('Cervantes y el quijote','Bioy Casares- J.L.
Borges','Paidos',null,100);
insert into libros
values('Manual de PHP', 'J.C. Paez', 'Siglo XXI',31.80,120);
insert into libros
values('Harry Potter y la piedra filosofal','J.K. Rowling',default,45.00,90);
insert into libros
values('Harry Potter y la camara secreta','J.K. Rowling','Emece',null,100);
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll','Paidos',22.50,200);
insert into libros
values('PHP de la A a la Z',null,null,null,0);

Queremos saber la cantidad de libros de cada editorial, utilizando la cláusula "group by":

select editorial, count(*)


from libros
group by editorial;

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.

Obtenemos la cantidad libros con precio no nulo de cada editorial:

select editorial, count(precio)


from libros
group by editorial;

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:

select editorial, sum(precio)


from libros
group by editorial;

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;

Calculamos el promedio del valor de los libros agrupados por editorial:

select editorial, avg(precio)


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:

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;

8 - Seleccionar grupos (having)

Así como la cláusula "where" permite seleccionar (o rechazar) registros individuales; la


cláusula "having" permite seleccionar (o rechazar) un grupo de registros.

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;

Se utiliza "having", seguido de la condición de búsqueda, para seleccionar ciertas filas


retornadas por la cláusula "group by".
Veamos otros ejemplos. Queremos el promedio de los precios de los libros agrupados por
editorial, pero solamente de aquellos grupos cuyo promedio supere los 25 pesos:
select editorial, avg(precio) from libros
group by editorial
having avg(precio)>25;

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".

Analicemos las siguientes sentencias:


select editorial, count(*) from libros
where editorial<>'Planeta'
group by editorial;
select editorial, count(*) from libros
group by editorial
having 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".

No debemos confundir la cláusula "where" con la cláusula "having"; la primera establece


condiciones para la selección de registros de un "select"; la segunda establece condiciones
para la selección de registros de una salida "group by".

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".

Se emplea la cláusula "having" con funciones de agrupamiento, esto no puede hacerlo la


cláusula "where". Por ejemplo queremos 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;

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:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

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)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Planeta',35,null);
insert into libros
values('Martin Fierro','Jose Hernandez','Emece',22.20,200);
insert into libros
values('Martin Fierro','Jose Hernandez','Planeta',40,200);
insert into libros
values('Antologia poetica','J.L. Borges','Planeta',null,150);
insert into libros
values('Aprenda PHP','Mario Molina','Emece',18,null);
insert into libros
values('Manual de PHP', 'J.C. Paez', 'Siglo XXI',56,120);
insert into libros
values('Cervantes y el quijote','Bioy Casares- J.L.
Borges','Paidos',null,100);
insert into libros
values('Harry Potter y la piedra filosofal','J.K. Rowling',default,45.00,90);
insert into libros
values('Harry Potter y la camara secreta','J.K. Rowling','Emece',null,100);
insert into libros
values('Alicia en el pais de las maravillas','Lewis Carroll','Paidos',42,80);
insert into libros
values('PHP de la A a la Z',null,null,110,0);
insert into libros
values('Uno','Richard Bach','Planeta',25,null);

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;

Queremos el promedio de los precios de los libros agrupados por editorial, pero solamente de aquellos
grupos cuyo promedio supere los 25 pesos:

select editorial, avg(precio) from libros


group by editorial
having avg(precio)>25;

Queremos la cantidad de libros, sin considerar los que tienen precio nulo (where), agrupados por editorial
(group by), sin considerar la editorial "Planeta" (having):

select editorial, count(*) from libros


where precio is not null
group by editorial
having editorial<>'Planeta';

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:

select editorial, max(precio) as 'mayor'


from libros
group by editorial
having max(precio)<100 and
max(precio)>30
order by editorial;

9 - Modificador del group by (with rollup)

Podemos combinar "group by" con los operadores "rollup" y "cube" para generar valores de
resumen a la salida.

El operador "rollup" resume valores de grupos. Representan los valores de resumen de la


precedente.

Tenemos la tabla "visitantes" con los siguientes campos: nombre, edad, sexo, domicilio,
ciudad, telefono, montocompra.

Si necesitamos la cantidad de visitantes por ciudad empleamos la siguiente sentencia:


select ciudad,count(*) as cantidad
from visitantes
group by ciudad;

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.

Si 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 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".

Con "rollup" se puede agrupar hasta por 10 campos.

Es posible incluir varias funciones de agrupamiento, por ejemplo, queremos la cantidad de


visitantes y la suma de sus compras agrupados por ciudad y sexo:
select ciudad,sexo,
count(*) as cantidad,
sum(montocompra) as total
from visitantes
group by ciudad,sexo
with rollup;

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.

Eliminamos la tabla si existe:

if object_id('visitantes') is not null


drop table visitantes;

La creamos con la siguiente estructura:

create table visitantes(


nombre varchar(30),
edad tinyint,
sexo char(1),
domicilio varchar(30),
ciudad varchar(20),
telefono varchar(11),
montocompra decimal(6,2) not null
);

Ingresamos algunos registros:

insert into visitantes


values ('Susana Molina',28,'f',null,'Cordoba',null,45.50);
insert into visitantes
values ('Marcela Mercado',36,'f','Avellaneda 345','Cordoba','4545454',22.40);
insert into visitantes
values ('Alberto Garcia',35,'m','Gral. Paz 123','Alta
Gracia','03547123456',25);
insert into visitantes
values ('Teresa Garcia',33,'f',default,'Alta Gracia','03547123456',120);
insert into visitantes
values ('Roberto Perez',45,'m','Urquiza 335','Cordoba','4123456',33.20);
insert into visitantes
values ('Marina Torres',22,'f','Colon 222','Villa Dolores','03544112233',95);
insert into visitantes
values ('Julieta Gomez',24,'f','San Martin 333','Alta Gracia',null,53.50);
insert into visitantes
values ('Roxana Lopez',20,'f','null','Alta Gracia',null,240);
insert into visitantes
values ('Liliana Garcia',50,'f','Paso 999','Cordoba','4588778',48);
insert into visitantes
values ('Juan Torres',43,'m','Sarmiento 876','Cordoba',null,15.30);

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.

10 - Modificador del group by (with cube)

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;

retorna más filas extras además de las anteriores:


- sexo y seccion (estadocivil seteado a "null"),
- estadocivil y seccion (sexo seteado a "null"),
- seccion (sexo y estadocivil seteados a "null") y
- estadocivil (sexo y seccion seteados a "null"),

Es decir, "cube" genera filas de resumen de subgrupos para todas las combinaciones posibles
de los valores de los campos por los que agrupamos.

Se pueden colocar hasta 10 campos en el "group by".

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:

if object_id('empleados') is not null


drop table empleados;

Créela con la siguiente estructura:

create table empleados (


documento varchar(8) not null,
nombre varchar(30),
sexo char(1),
estadocivil char(1),--c=casado, s=soltero,v=viudo
seccion varchar(20),
primary key (documento)
);

Ingrese algunos registros:

insert into empleados


values ('22222222','Alberto Lopez','m','c','Sistemas');
insert into empleados
values ('23333333','Beatriz Garcia','f','c','Administracion');
insert into empleados
values ('24444444','Carlos Fuentes','m','s','Administracion');
insert into empleados
values ('25555555','Daniel Garcia','m','s','Sistemas');
insert into empleados
values ('26666666','Ester Juarez','f','c','Sistemas');
insert into empleados
values ('27777777','Fabian Torres','m','s','Sistemas');
insert into empleados
values ('28888888','Gabriela Lopez','f','c','Sistemas');
insert into empleados
values ('29999999','Hector Garcia','m','c','Administracion');
insert into empleados
values ('30000000','Ines Torres','f','c','Administracion');
insert into empleados
values ('11111111','Juan Garcia','m','v','Administracion');
insert into empleados
values ('12222222','Luisa Perez','f','v','Administracion');
insert into empleados
values ('31111111','Marcela Garcia','f','s','Administracion');
insert into empleados
values ('32222222','Nestor Fuentes','m','c','Sistemas');
insert into empleados
values ('33333333','Oscar Garcia','m','s','Sistemas');
insert into empleados
values ('34444444','Patricia Juarez','f','c','Administracion');
insert into empleados
values ('35555555','Roberto Torres','m','c','Sistemas');
insert into empleados
values ('36666666','Susana Torres','f','c','Administracion');

Agrupamos por "sexo", "estadocivil" y "seccion" empleando "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 e hijos seteados a "null") y
- total (todos los campos seteados a "null").

Si empleamos "cube":

select sexo,estadocivil,seccion,
count(*) from empleados
group by sexo,estadocivil,seccion
with cube;

retorna más filas extras además de las anteriores:

- sexo y seccion (estadocivil seteado a "null"),


- estadocivil y seccion (sexo seteado a "null"),
- seccion (sexo y estadocivil seteados a "null") y
- estadocivil (sexo e hijos seteados a "null").

También podría gustarte