domingo, 5 de mayo de 2013

61 - Funciones de control de flujo (case)



La función "case" es similar a la función "if", sólo que se pueden establecer varias condiciones a cumplir.
Trabajemos con la tabla "libros" de una librería.

Queremos saber si la cantidad de libros de cada editorial es menor o mayor a 1, tipeamos:

 select editorial,
  if (count(*)>1,'Mas de 2','1') as 'cantidad'
  from libros
  group by editorial;
 
vemos los nombres de las editoriales y una columna "cantidad" que especifica si hay más o menos de uno. Podemos obtener la misma salida usando un "case":

 select editorial,
  case count(*)
   when 1 then 1
   else 'mas de 1' end as 'cantidad'
  from libros
  group by editorial;
 
Por cada valor hay un "when" y un "then"; si encuentra un valor coincidente en algún "where" ejecuta el "then" correspondiente a ese "where", si no encuentra ninguna coincidencia, se ejecuta el "else", si no hay parte "else" retorna "null". Finalmente se coloca "end" para indicar que el "case" ha finalizado.

Entonces, la sintaxis es:

 case  
  when  then 
  ...
  else  end
 
Se puede obviar la parte "else":

 select editorial,
  case count(*)
   when 1 then 1
   end as 'cantidad'
  from libros
  group by editorial;
 
Con el "if" solamente podemos obtener dos salidas, cuando la condición resulta verdadera y cuando es falsa, si queremos más opciones podemos usar "case". Vamos a extender el "case" anterior para mostrar distintos mensajes:

 select editorial,
  case count(*)
   when 1 then 1
   when 2 then 2
   when 3 then 3
  else 'Más de 3' end as 'cantidad'
  from libros
  group by editorial;
 
Incluso podemos agregar una cláusula "order by" y ordenar la salida por la columna "cantidad":

 select editorial,
  case count(*)
   when 1 then 1
   when 2 then 2
   when 3 then 3
  else 'Más de 3' end as 'cantidad'
  from libros
  group by editorial
  order by cantidad;
 
La diferencia con "if" es que el "case" toma valores puntuales, no expresiones. La siguiente sentencia provocará un error:

 select editorial,
  case count(*)
   when 1 then 1
   when >1 then 'mas de 1'
  end as 'cantidad'
  from libros
  group by editorial;
 
Pero existe otra sintaxis de "case" que permite condiciones:

 case
  when  then 
  ...
  else 
 end
 
Veamos un ejemplo:

 select editorial,
  case
   when count(*)=1 then 1
   else 'mas de uno'
  end as cantidad
  from libros
  group by editorial;
 
 
 
PROBLEMA RESUELTO 
 




Trabajamos con la tabla "libros" de una librería.
Eliminamos la tabla si existe:
 drop table if exists libros;
Creamos la tabla:
 create table libros(
  codigo int unsigned auto_increment,
  titulo varchar(40) not null,
  autor varchar(30),
  editorial varchar(20),
  precio decimal(5,2) unsigned,
  cantidad smallint unsigned,
  primary key(codigo)
 );
Ingresamos algunos registros:
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('El aleph','Borges','Planeta',34.5,100);
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('Alicia en el pais de las maravillas','Carroll L.','Paidos',20.7,50);
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('harry Potter y la camara secreta',null,'Emece',35,500);
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('Aprenda PHP','Molina Mario','Planeta',54,100);
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('Harry Potter y la piedra filosofal',null,'Emece',38,500);
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('Aprenda Java','Molina Mario','Planeta',55,100);
 insert into libros (titulo,autor,editorial,precio,cantidad)
  values('Aprenda JavaScript','Molina Mario','Planeta',58,150);
Queremos saber si la cantidad de libros de cada editorial es menor o mayor a 1 empleando "case":
 select editorial,
  case count(*)
   when 1 then 1
   else 'mas de 1' end as 'cantidad'
  from libros
  group by editorial;
Por cada valor hay un "when" y un "then"; si encuentra un valor coincidente en algún "where" ejecuta el "then" correspondiente a ese "where", si no encuentra ninguna coincidencia, se ejecuta el "else", si no hay parte "else" retorna "null". Finalmente se coloca "end" para indicar que el "case" ha finalizado. Veamos un ejemplo sin parte "else":
 select editorial,
  case count(*)
   when 1 then 1
   end as 'cantidad'
  from libros
  group by editorial;
Extendamos el "case" para mostrar distintos mensajes comparando más de 2 valores:
 select editorial,
  case count(*)
   when 1 then 1
   when 2 then 2
   when 3 then 3
  else 'Más de 3' end as 'cantidad'
  from libros
  group by editorial;
Agregamos la cláusula "order by" para ordenar la salida por la columna "cantidad":
 select editorial,
  case count(*)
   when 1 then 1
   when 2 then 2
   when 3 then 3
  else 'Más de 3' end as 'cantidad'
  from libros
  group by editorial
  order by cantidad;
"case" toma valores puntuales, no expresiones. Intentemos lo siguiente:
 select editorial,
  case count(*)
   when 1 then 1
   when >1 then 'mas de 1'
  end as 'cantidad'
  from libros
  group by editorial;
Usemos la otra sintaxis de "case":
 select editorial,
  case when count(*)=1 then 1
       else 'mas de 1'
  end as 'cantidad'
 from libros
 group by editorial;
PROBLEMA PROPUESTO
Un profesor guarda los promedios de sus alumnos de un curso en una tabla 
llamada "alumnos".
 
1- Elimine la tabla si existe.
 
2- Cree la tabla:
 create table alumnos(
  legajo char(5) not null,
  nombre varchar(30),
  promedio decimal(4,2)
);
 
3- Ingrese los siguientes registros:
 insert into alumnos values(3456,'Perez Luis',8.5);
 insert into alumnos values(3556,'Garcia Ana',7.0);
 insert into alumnos values(3656,'Ludueña Juan',9.6);
 insert into alumnos values(2756,'Moreno Gabriela',4.8);
 insert into alumnos values(4856,'Morales Hugo',3.2);
 insert into alumnos values(7856,'Gomez Susana',6.4);
 
4- Si el alumno tiene un promedio menor a 4, muestre un mensaje "reprobado", 
si el promedio es mayor o igual a 4 y menor a 7, muestre "regular", si el 
promedio es mayor o igual a 7, muestre "promocionado", usando la primer 
sintaxis de "case":
 
5- Obtenga la misma salida anterior pero empleando la otra sintaxis de "case":
 

Otros problemas:
A) Una playa de estacionamiento guarda cada día los datos de los vehículos que ingresan a la playa 
en una tabla llamada "vehiculos".
 
1- Elimine la tabla, si existe.
 
2- Cree la tabla:
 create table vehiculos(
  patente char(6) not null,
  tipo char(4),
  horallegada time not null,
  horasalida time,
  primary key(patente,horallegada)
 );
 
3- Ingrese algunos registros:
 insert into vehiculos (patente,tipo,horallegada,horasalida)
  values('ACD123','auto','8:30','9:40');
 insert into vehiculos (patente,tipo,horallegada,horasalida)
  values('AKL098','auto','8:45','15:10');
 insert into vehiculos (patente,tipo,horallegada,horasalida)
  values('HGF123','auto','9:30','18:40');
 insert into vehiculos (patente,tipo,horallegada,horasalida)
  values('DRT123','auto','15:30',null);
 insert into vehiculos (patente,tipo,horallegada,horasalida)
  values('FRT545','moto','19:45',null);
 insert into vehiculos (patente,tipo,horallegada,horasalida)
  values('GTY154','auto','20:30','21:00');
 
4- Se cobra 1 peso por hora. Pero si un vehículo permanece en la playa 
4 horas, se le cobran 3 pesos, es decir, no se le cobra la cuarta hora; 
si está 8 horas, se cobran 6 pesos, y así sucesivamente. Muestre la patente, 
la hora de llegada y de salida de todos los vehículos, más la columna que 
calcule la cantidad de horas que estuvo cada vehículo en la playa (sin 
considerar los que aún no se retiraron de la playa) y otra columna utilizando 
"case" que muestre la cantidad de horas gratis:

5- Muestre la patente, la hora de llegada y de salida de todos los vehículos, 
más una columna que calcule la cantidad de horas que estuvo cada vehículo en 
la playa (sin considerar los que aún no se retiraron de la playa) y otra 
columna (con "case") que calcule la cantidad de horas cobradas:
 
   
B) En una página web se solicitan los siguientes datos para guardar información
de sus visitas.
 
1- Elimine la tabla "visitas", si existe.
 
2- Créela con la siguiente estructura:
 create table visitas (
  numero int unsigned auto_increment,
  nombre varchar(30) not null,
  mail varchar(50),
  pais varchar (20),
  fecha date,
  primary key(numero)
);
 
3- Ingrese algunos registros:
 insert into visitas (nombre,mail,fecha)
  values ('Ana Maria Lopez','AnaMaria@hotmail.com','2006-02-10');
 insert into visitas (nombre,mail,fecha)
  values ('Gustavo Gonzalez','GustavoGGonzalez@hotmail.com','2006-05-10');
 insert into visitas (nombre,mail,fecha)
  values ('Juancito','JuanJosePerez@hotmail.com','2006-06-11');
 insert into visitas (nombre,mail,fecha)
  values ('Fabiola Martinez','MartinezFabiola@hotmail.com','2006-10-12');
 insert into visitas (nombre,mail,fecha)
  values ('Fabiola Martinez','MartinezFabiola@hotmail.com','2006-09-12');
 insert into visitas (nombre,mail,fecha)
  values ('Juancito','JuanJosePerez@hotmail.com','2006-09-12');
 insert into visitas (nombre,mail,fecha)
  values ('Juancito','JuanJosePerez@hotmail.com','2006-09-15');
 insert into visitas (nombre,mail,fecha)
  values ('Juancito','JuanJosePerez@hotmail.com','2006-09-15');
 
4- Muestre el nombre, la fecha de ingreso y los nombres de los días de la 
semana empleando un "case": 
 


5- Muestre el nombre y fecha de ingreso a la página y con un "case" muestre 
si el nombre del mes corresponde al 1º, 2º o 3º cuatrimestre del año.
 
 


 

 



1 comentario: