Vous êtes sur la page 1sur 8

Gua de ejercicios de SQL

Prof. Claudio Gutirrez, Aux. Mauricio Monsalve Otoo de 2008

[P1] Corretaje de propiedades


Enunciado Sean las siguientes tablas de una base de datos de una corredora de propiedades:
Arrendatario(RUT,Nombre,Apellido) Arrienda(RUT,Id_casa,Deuda)Ojo:Deuda>=0(sies0,nohaydeuda) Telefonos(RUT,Fono) Dueo(RUT,Nombre,Apellido) Casa(Id_casa,RUT,Nro,Calle,Comuna)

Al respecto, conteste las siguientes preguntas: 1. Los arrendatarios que arriendan la casa ubicada en la calle Carrera n 1024, Santiago. 2. Cunto le deben a Mara Prez? 3. Cul es la deuda total para cada dueo? 4. Liste todas las personas de la base de datos 5. Indique los dueos que poseen tres o ms casas. 6. Liste los dueos que tengan deudores en todas sus casas. 7. Entregue estadsticas sobre los arrendatarios por casa. Entregue: 1. El promedio. 2. La varianza. 3. El mximo. 4. El mnimo. 5. La moda. 6. La mediana. Solucin Recomendacin: evite colocar selects en el from. Prefiera no anidar de esa manera; muchas veces eso se puede escribir dentro de where.

1. Este es el tipo ms sencillo de consulta posible.


SELECTA.RUT,A.Nombre,A.Apellido FROMArrendatarioA,ArriendaB,CasaC WHEREA.RUT=B.RUTANDB.Id_casa=C.Id_casa ANDC.Calle='Carrera'ANDC.Nro='1024'ANDC.Comuna='Santiago';

2. Se supondr que Mara Prez hay una sola.


SELECTSUM(A.Deuda)FROMArriendaA,CasaB,DueoC WHEREA.Id_casa=B.Id_casaANDB.RUT=C.RUT ANDC.Nombre='Mara'ANDC.Apellido='Prez';

3. Aqu es necesario agrupar la informacin, as la suma se har dentro de cada grupo indicado. Entregu toda la informacin necesaria en el SELECT, aunque con el RUT del dueo bastara (si en el trabajo le piden algo as, entregue todo).
SELECTSUM(A.Deuda),C.RUT,C.Nombre,C.Apellido FROMArriendaA,CasaB,DueoC WHEREA.Id_casa=B.Id_casaANDB.RUT=C.RUT GROUPBYC.RUT;

4. Las personas de la BD son los arrendatarios y los dueos. Para entregar ambos, hay que realizar una unin. Nota: para realizar una unin, los esquemas deben ser compatibles (atributos con mismo nombre y dominio). Afortunadamente, ste es el caso.
SELECT*FROMArrendatarioUNIONSELECT*FROMDueo;

5. Hay dos maneras de hacer esto: con agregacin y sin sta. El caso sin agregacin (menos evidente en general) consiste en hacer un join de tres tablas. Sin agregacin:
SELECTA.RUT,A.Nombre,A.Apellido FROMDueoA,CasaC1,CasaC2,CasaC3 WHEREA.RUT=C1.RUTANDC1.RUT=C2.RUTANDC2.RUT=C3.RUT ANDC1.Id_casa<>C2.Id_casaANDC1.Id_casa<>C3.Id_casa ANDC2.Id_casa<>C3.Id_casa;

Con agregacin: en este caso, es necesario utilizar HAVING. HAVING es el WHERE pero para funciones agregadas. En el HAVING slo pueden aparecer funciones agregadas y constantes.
SELECTA.RUT,A.Nombre,A.Apellido FROMDueoA,CasaC WHEREA.RUT=C.RUT GROUPBYA.RUT HAVINGCOUNT(DISTINCTC.Id_casa)>=3;

6. Jugando con la semntica vemos que un dueo con deudores en todas sus casas equivale a un dueo con deuda en todas sus casas. Y el complemento de eso son los dueos con casas sin deudas.
SELECTD.RUT,D.Nombre,D.Apellido FROMDueoD,CasaC WHERED.RUT=C.RUT EXCEPT SELECTD.RUT,D.Nombre,D.Apellido FROMDueoD,CasaC,ArriendaA WHERED.RUT=C.RUTANDC.Id_casa=A.Id_casaANDA.Deuda>0

Otra manera consiste en exigir que la deuda de cada casa del dueo sea positiva. En este caso, una consulta anidada exigiendo igualdad sobre ALL basta.
SELECTD.RUT,D.Nombre,D.Apellido FROMDueoD,CasaC WHERED.RUT=C.RUT AND0=ALL( SELECTA.Deuda FROMArriendaA WHEREC.Id_casa=A.Id_casa) ORNOTEXISTS( SELECT* FROMArriendaA WHEREC.Id_casa=A.Id_casa);

Esto es equivalente a lo anterior: que no exista (NOT EXISTS) una casa con deuda para este dueo. De hecho, es ms eficiente.
SELECTD.RUT,D.Nombre,D.Apellido FROMDueoD,CasaC WHERED.RUT=C.RUT

ANDNOTEXISTS( SELECT* FROMArriendaA WHEREC.Id_casa=A.Id_casaANDA.Deuda>0);

7. En esta seccin veremos cmo calcular estadsticas con SQL estndar. El promedio de arrendatarios por casa: la manera correcta de hacerlo es considerar todos los arrendatarios que efectivamente arrienden y todas las casas. As se contarn las casas con 0 arrendatarios, que deberan ser consideras en el promedio.
SELECTDISTINCTCOUNT(DISTINCTA.RUT)/COUNT(DISTINCTB.Id_casa) FROMArriendaA,CasaB;

El mximo requiere una consulta anidada sencilla. Hay que contar el nmero de arrendatarios por cada grupo y exigir que sea mayor a los de los dems grupos. Esta consulta tiene un error. Cul es?1 Cmo se corrige?
SELECTCOUNT(A.RUT) FROMArriendaA GROUPBYA.Id_casa HAVINGCOUNT(A.RUT)>=ALL( SELECTCOUNT(B.RUT) FROMArriendaB GROUPBYB.Id_casa);

El mnimo es anlogo. Esta consulta tiene un error. Cul es? Cmo se corrige?
SELECTCOUNT(A.RUT) FROMArriendaA GROUPBYA.Id_casa HAVINGCOUNT(A.RUT)<=ALL( SELECTCOUNT(B.RUT) FROMArriendaB GROUPBYB.Id_casa);

Ahora necesito la siguiente consulta: el nmero de arrendatarios por casa. Se advierte que la prctica de realizar consultas anidadas en el FROM se debe evitar si se puede usar IN, NOT IN, EXISTS, ALL, etc.
(*)= SELECTId_casaASID,COUNT(DISTINCTRUT)ASN FROMArrienda GROUPBYId_casa
1 Hint: puede que el error est cerca del operador de agregacin...

UNION SELECTId_casaASID,0ASN FROMCasa WHEREId_casaNOTIN( SELECTX.Id_casa FROMArriendaX);

La varianza es la desviacin de la media. Puesto que dos operaciones agregadas son necesarias para resolver esto, forzosamente necesitamos realizar una consulta previa e incluirla en el FROM. Frmula: Var[X]=E[X2]E2[X]
SELECTSUM(N*N)/COUNT(ID)AVG(N)*AVG(N) FROM(*);

La moda es la frecuencia ms repetida. La frecuencia es el COUNT, por ende aplico la comparacin en el HAVING.
SELECTX.N FROM(*)X GROUPBYX.N HAVINGCOUNT(DISTINCTX.ID)>=ALL( SELECTCOUNT(DISTINCTY.ID) FROM(*)Y GROUPBYY.N);

La mediana es la frecuencia central. Se supondr que es nica.


SELECTDISTICTX.N FROM(*)X,(*)Y,(*)Z WHEREX.N>Y.NANDX.N<Z.N GROUPBYX.N HAVINGCOUNT(DISTINCTY.ID)=COUNT(DISTINCTZ.ID);

Propuesto: Cmo se puede hacer en los casos con, por ejemplo, 4 candidatos? Algo como: 0 0 0 0 1 2 3 3 4 4 4 4 5 5 6 7 8 9 9 11. No es mucho ms complicado que la consulta anterior puesto que hay que hacer una pequea observacin para contestar la pregunta.

[P2] Sistema de e-learning


Enunciado Noob Saiborg2 est desarrollando un sistema de evaluacin automtico como parte de un paquete de e-learning comercial. En este sistema, los tests consisten de 1 ms preguntas con alternativas. Para hacer el sistema flexible, y para aumentar la dificultad de los problemas, uno de los requerimientos es que las preguntas -de las que consisten los tests- tengan una o ms soluciones. (Por ejemplo, una pregunta del tipo Cul de las siguientes propiedades presenta el paradigma OOP? requiere la seleccin de varias alternativas.) Actualmente, Noob S. cuenta con el siguiente modelo de datos relacional para modelar los tests:
test(tnum,titulo,curso,descripcion,autor) preg(tnum,pnum,enunciado) pregalt(tnum,pnum,alt,texto,correcta)//correctaesbooleana resp(user,tnum,pnum,alt) alumno(user,nombre,apellido) cursa(user,curso) contesta(user,tnum) cursos(curso,nombre)

En este sencillo (primitivo) modelo de datos, Noob S. necesita resolver los siguientes problemas con SQL: 1. Sobrescribir el test X con otro test Y. (X,Y son tnum) 2. Conocer el nmero de tests por curso. 3. Conocer los cursos sin tests. 4. Determinar los tests con falencias. Un test tiene falencias si no tiene preguntas, si su primera pregunta (pnum) no est numerada 1, si las preguntas no son consecutivas (ej. 1,2,4,5,8), si hay preguntas con 1 menos alternativas3, si todas las alternativas son verdaderas o si todas las alternativas son falsas. 5. Corregir los test cuya nica falencia radica en la numeracin de las preguntas. 6. Cuntos alumnos hay en cada curso. 7. Qu alumnos han contestado tests que no les corresponden (de cursos que no cursan). 8. Obtener el puntaje no normalizado de cada rendicin de test. El puntaje no normalizado ha sido definido (requerimiento) como: P = buenas malas/4. Si un alumno no contesta en una pregunta exactamente lo mismo que se ha definido como correcto, la pregunta cuenta como mala a menos que el alumno haya omitido. 9. Obtener el puntaje normalizado, o sea, de 1,0 a 7,0. Solucin Para resolver este problema es necesario saber cmo escribir consultas y cmo modificar datos con SQL.
2 Chiste fome MK2. Noob Saibot = Boon Tobias. 3 Esto es semnticamente incorrecto. Una seleccin mltiple es, en s misma, una alternativa. Pero en general se entiende que una opcin y una alternativa son lo mismo. (Opcin es el trmino correcto.)

[1] Sobrescribir el test X con el test Y se hace borrando el test X y copiando los datos del test Y con el tnum X. Haremos el proceso completo de borrado de un test, considerando si el test fue contestado, y copiaremos los datos de Y.
deletefromtestwheretnum=X; deletefrompregwheretnum=X; deletefromaltwheretnum=X; deletefromcontestawheretnum=X; deletefromrespwheretnum=X; insertintotestselectX,titulo,curso,descripcion,autor fromtestwheretnum=Y; insertintopregselectX,pnum,enunciado frompregwheretnum=Y; insertintopregaltselectX,pnum,alt,texto,correcta frompregaltwheretnum=Y;

[2] El nmero de tests por curso tiene la forma (curso, nmero). Es una simple y vil agrupacin con count(*).
selectcurso,count(*) fromtest groupbycurso;

[3] Una simple sustraccin.


selectcursofromcursos except selectcursofromtest;

[4] Cada exigencia del enunciado puede ser consultada por separado y luego unida para obtener los tnum que corresponden a tests invlidos.
( selecttnumfromtest EXCEPTselecttnumfrompreg ) UNION ( selecttnumfrompreg groupbytnumhavingmin(pnum)<1 )

UNION ( selecttnumfrompreg groupbytnumhavingmax(pnum)<>count(pnum) ) UNION ( selecttnumfrompregalt groupbytnum,pnumhavingcount(alt)=1 ) UNION ( selecttnumfrom(selecttnum,pregfrompreg EXCEPTselecttnum,pregfrompregalt) ) UNION ( selecttnumfrompregalt groupbytnum,althavingcount(distinctcierta)=1 );

El resto de las preguntas se dejan como ejercicios propuestos.

Vous aimerez peut-être aussi