Reporte de Práctica 2: Bases de Datos No Relacionales
Este documento sirve como bitácora de los comandos y consultas ejecutadas en el entorno Oracle 11g XE configurado a través de Docker en el servidor AlmaLinux.
1. Preparación del Entorno (Ejecutado por el sistema)
Se levantó un contenedor Docker con Oracle 11g y se preparó una carpeta interna para emular la ruta solicitada en la práctica.
- Ruta local en la práctica (Windows):
c:\repositorio - Ruta configurada en nuestro servidor (Linux/Docker):
/opt/oracle/oradata/repositorio
2. Creación del usuario y permisos (Ejecutado como SYSDBA)
Se creó el usuario bdxml requerido por la práctica y se le otorgaron los permisos para conectarse, crear recursos y administrar directorios.
CONNECT / AS SYSDBA;
CREATE USER bdxml IDENTIFIED BY bdxml;
GRANT CONNECT, RESOURCE TO bdxml;
GRANT CREATE ANY DIRECTORY TO bdxml;
GRANT DROP ANY DIRECTORY TO bdxml;
Explicación: Estos comandos preparan la cuenta de usuario que usaremos para toda la práctica. El permiso de crear directorios es fundamental para que Oracle pueda leer archivos externos (como nuestros XML).
3. Configuración de Sesión y Creación de Tabla (Ejecutado como bdxml)
Nos conectamos con el nuevo usuario, ajustamos la región y creamos la primera tabla que almacenará documentos XML directamente en la base de datos usando el tipo de dato XMLType.
CONNECT bdxml/bdxml;
-- Ajusta la configuración regional para fechas y monedas
ALTER SESSION SET NLS_TERRITORY='MEXICO';
-- Crea la tabla para almacenar la información personal y el Curriculum Vitae en formato XML
CREATE TABLE personas (
RFC CHAR(13) PRIMARY KEY,
Nombre VARCHAR(30) NOT NULL,
Apellidos VARCHAR(30) NOT NULL,
CV XMLType
);
Explicación: El tipo de dato XMLType es la característica clave aquí, ya que permite a Oracle validar que el documento XML esté bien formado y nos habilitará el uso de funciones como EXTRACT y XQuery más adelante.
4. Inserción de Datos y Consultas (Sección 3.1.1)
Se ejecutaron los 4 INSERT correspondientes a la práctica que incluyen documentos XML dentro de la estructura relacional. Posteriormente se corrieron las 12 consultas solicitadas en la práctica.
Resultados de las Consultas
Consulta 1: Selección completa de la tabla
SELECT * FROM personas;
RFC NOMBRE APELLIDOS
--------------- ------------------------------ ------------------------------
PELJ900304JJ6 Juan Pérez López
CACM871109LI8 Martha Carbajal Carbajal
CALJ851211K9O Juan Manuel Camacho López
MEGR910508PY3 Rodrigo Medina García
Consulta 2: Formatear a atributo XML
SELECT XMLColattval(p.apellidos) FROM personas p;
XMLCOLATTVAL(P.APELLIDOS)
---------------------------------------------------------------------------------------------------
<column name = "APELLIDOS">Pérez López</column>
<column name = "APELLIDOS">Carbajal Carbajal</column>
<column name = "APELLIDOS">Camacho López</column>
<column name = "APELLIDOS">Medina García</column>
Consulta 3: Extraer todas las empresas de “Martha”
SELECT p.nombre || ' ' || p.apellidos AS persona, EXTRACT(p.cv, '//empresa').getstringval() AS RESULT FROM personas p WHERE p.nombre LIKE '%Martha%';
PERSONA RESULT
------------------------------ --------------------------------------------------------------------------------
Martha Carbajal Carbajal <empresa>Comercializadora de Ropa del Centro </empresa>
<empresa>Refacciones para Autobuses S.A.</empresa>
Consulta 4: Extraer la empresa que contenga “S.A.”
SELECT p.nombre || ' ' || p.apellidos AS persona, EXTRACTVALUE(p.cv,'//empresa[contains(.,"S.A.")]') AS RESULT FROM personas p;
PERSONA RESULT
------------------------------ --------------------------------------------------------------------------------
Juan Pérez López
Martha Carbajal Carbajal Refacciones para Autobuses S.A.
Juan Manuel Camacho López Asesores Fiscales S.A.
Rodrigo Medina García
Consulta 5: Validar que exista el nodo y extraer “S.A.”
SELECT p.nombre || ' ' || p.apellidos AS persona, EXTRACTVALUE(p.cv, '//empresa[contains(.,"S.A.")]') AS RESULT FROM personas p WHERE EXISTSNODE(p.cv, '//empresa[contains(.,"S.A.")]') = 1;
PERSONA RESULT
------------------------------ --------------------------------------------------------------------------------
Martha Carbajal Carbajal Refacciones para Autobuses S.A.
Juan Manuel Camacho López Asesores Fiscales S.A.
Consulta 6: Búsqueda con operador OR (|)
SELECT p.nombre || ' ' || p.apellidos AS persona, EXTRACT(p.cv, '//medio_superior/escuela/text() | //superior/escuela/text()').getstringval() AS RESULT FROM personas p WHERE EXISTSNODE(p.cv, '//medio_superior/comprobante | //superior/comprobante') = 1;
PERSONA RESULT
------------------------------ --------------------------------------------------------------------------------
Juan Pérez López Escuela preparatoria No.5
Martha Carbajal Carbajal Vocacional No. 3 Escuela Internacional de Comercio C.V.
Juan Manuel Camacho López Escuela Comercial y Contable
Consulta 7: Buscar personas con más de 1 empleo
SELECT p.nombre || ' ' || p.apellidos AS persona, EXTRACT(p.cv, '//empleos/empleo/empresa/text()').getstringval() AS RESULT FROM personas p WHERE EXISTSNODE(p.cv, '//empleos[count(empleo)>1]') = 1;
PERSONA RESULT
------------------------------ --------------------------------------------------------------------------------
Juan Pérez López Fábricas de Cartón Comercializadora Internacional
Martha Carbajal Carbajal Comercializadora de Ropa del Centro Refacciones para Autobuses S.A.
Juan Manuel Camacho López Banca de Desarrollo Empresarial Asesores Fiscales S.A.
Consulta 8: Extraer comprobante de “Martha”
SELECT p.rfc, p.nombre || ' ' || p.apellidos AS persona, EXTRACT(p.cv, '//comprobante').getstringval() AS RESULT FROM personas p WHERE p.nombre LIKE '%Martha%';
RFC PERSONA RESULT
--------------- ------------------------------ --------------------------------------------------------------------------------
CACM871109LI8 Martha Carbajal Carbajal <comprobante>certificado</comprobante>
<comprobante>titulo profesional</comprobante>
Consulta 9 y 10: Actualizar un nodo XML con UpdateXML
UPDATE personas p SET p.cv = updateXML(p.cv, '//medio_superior/comprobante', '<comprobante>diploma</comprobante>') WHERE p.rfc = 'CACM871109LI8';
[Salida de la Consulta 10 mostrando la actualización]
RFC PERSONA RESULT
--------------- ------------------------------ --------------------------------------------------------------------------------
CACM871109LI8 Martha Carbajal Carbajal <comprobante>diploma</comprobante>
<comprobante>titulo profesional</comprobante>
Consulta 11 y 12: Eliminar un nodo XML con deleteXML
UPDATE personas p SET p.cv = deleteXML(p.cv, '//medio_superior/comprobante["diploma"]') WHERE p.rfc = 'CACM871109LI8';
[Salida de la Consulta 12 mostrando la eliminación]
RFC PERSONA RESULT
--------------- ------------------------------ --------------------------------------------------------------------------------
CACM871109LI8 Martha Carbajal Carbajal <comprobante>titulo profesional</comprobante>
5. Manejo de Archivos XML Externos (Sección 3.2)
Se preparó la base de datos para leer archivos XML alojados en el sistema de archivos del servidor (en nuestro caso, dentro del contenedor de Docker).
Creación de Tabla de tipo XML
CREATE TABLE empleados_xml OF XMLType;
SELECT TABLE_NAME FROM USER_XML_TABLES;
TABLE_NAME
------------------------------
EMPLEADOS_XML
Creación del Directorio Lógico
CREATE OR REPLACE DIRECTORY REPOSITORIO AS '/opt/oracle/oradata/repositorio';
Directory created.
Carga del Archivo y Configuración de Sesión
A continuación, utilizamos la función BFILENAME para leer el archivo empleados.xml que habíamos subido al contenedor y lo insertamos como una fila en nuestra tabla. Las variables de sesión se ajustaron para poder leer los XML largos.
INSERT INTO empleados_xml VALUES
(XMLType(BFILENAME('REPOSITORIO', 'empleados.xml'), NLS_CHARSET_ID('AL32UTF16')));
COMMIT;
-- Configuraciones de visualización en SQL*Plus
SET PAGESIZE 500;
SET LINESIZE 300;
SET LONG 2000;
COLUMN RESULT FORMAT A300;
1 row created.
Commit complete.
Consultas sobre el archivo cargado (Página 8)
Consulta A:
SELECT * FROM empleados_xml;
(Muestra el contenido crudo en formato XML de todos los empleados insertados).
Consulta B:
SELECT XMLRoot(e.OBJECT_VALUE, VERSION '1.0', STANDALONE YES) FROM empleados_xml e;
(Imprime el mismo árbol pero anteponiendo la declaración <?xml version="1.0" standalone="yes"?>).
Consulta C:
SELECT EXTRACT(e.OBJECT_VALUE,'/empleados/empleado/paterno').getstringval() AS res FROM empleados_xml e;
Resultado: Vacío. (Explicación: El nodo <paterno> no existe en el documento empleados.xml, el nodo correcto se llama <apellido>).
Consulta D:
SELECT EXTRACTVALUE(e.OBJECT_VALUE, '/empleados/empleado[@id=101]/paterno') AS res FROM empleados_xml e;
Resultado: Vacío. (Explicación: No existen atributos id en el documento, se usa el atributo NSS, además de que el nodo paterno no existe).
Consulta E:
SELECT EXTRACT(e.OBJECT_VALUE, '/empleados/empleado[sexo="F"]/nombre').getstringval() AS res FROM empleados_xml e;
Resultado: Vacío. (Explicación: El nodo para el género se llama <genero>, no <sexo>).
Consulta F:
SELECT EXTRACT(e.OBJECT_VALUE, '/empleados/empleado[sexo="F"]/nombre').getstringval() AS res FROM empleados_xml e WHERE existsNode(OBJECT_VALUE, '//proy') = 1;
Resultado: no rows selected. (Explicación: Ningún nodo coincide con las condiciones establecidas).
Consulta G:
SELECT EXTRACT(e.OBJECT_VALUE, '//empleado[sexo="F" and edad>="30"]/nombre').getstringval() AS res FROM empleados_xml e;
Resultado: Vacío. (Explicación: No existen los nodos sexo ni edad en el documento).
Consulta H:
SELECT XMLSerialize(DOCUMENT e.OBJECT_VALUE AS CLOB) AS XML FROM empleados_xml e;
(Muestra el documento casteado explícitamente a tipo Character Large Object).
Creación de Recursos en XDB (Páginas 8-11)
Se ejecutó el bloque de código PL/SQL masivo que construye dinámicamente dos cadenas con formato XML (una para empleados y otra para departamentos) y utiliza la función DBMS_XDB.createResource para inyectarlos en el repositorio XML interno de la base de datos bajo el directorio /public/.
DECLARE
res BOOLEAN;
empsxmlstring VARCHAR2(4000) := '';
deptsxmlstring VARCHAR2(4000) := '';
BEGIN
-- (Concatenaciones de strings XML omitidas en el reporte por brevedad) ...
res := DBMS_XDB.createResource('/public/empleados.xml', empsxmlstring);
res := DBMS_XDB.createResource('/public/departamentos.xml', deptsxmlstring);
END;
/
COMMIT;
PL/SQL procedure successfully completed.
Commit complete.
(Nota de ejecución: El bloque de la práctica tenía un ligero error de sintaxis en PL/SQL al intentar asignar variables antes de la declaración BEGIN. Se corrigió la estructura para que Oracle lo compilara y ejecutara sin problemas).
Consultas XQuery usando FLWOR (Sección 3.2.1)
Estas consultas utilizan XQuery y expresiones FLWOR (for, let, where, order by, return) para procesar e interrelacionar la información de los archivos almacenados en el repositorio interno /public/ de Oracle.
Consulta 1: Listar empleado y el nombre de su departamento
SELECT XMLQuery('for $e in doc("/public/empleados.xml")/empleados/empleado let $d := doc("/public/departamentos.xml")//departamento[@numero = $e/@departamento]/nombre return <empleado nombre="{$e/nombre}" departamento="{$d}"/>' RETURNING CONTENT) AS RESULT FROM DUAL;
RESULT
------------------------------------------------------------------------------------------------------------------------
<empleado nombre="Jesús" departamento="Administración"></empleado><empleado nombre="Guadalupe" departamento="Administrac
ión"></empleado><empleado nombre="Julia" departamento="Sistemas"></empleado><empleado nombre="Mario" departamento="Admin
istración"></empleado><empleado nombre="Rogelio" departamento="Ventas"></empleado><empleado nombre="Bruce" departamento=
"Sistemas"></empleado><empleado nombre="Laura" departamento="Ventas"></empleado><empleado nombre="Sandra" departamento="
Sistemas"></empleado><empleado nombre="Guadalupe" departamento="Ventas"></empleado>
Consulta 2: Empleados con salario > 10,000 (Concatenando nombre y apellido)
SELECT XMLQuery('for $e in doc("/public/empleados.xml")/empleados/empleado let $d := doc("/public/departamentos.xml")//departamento[@numero = $e/@departamento]/nombre where $e/salario > 10000 order by $e/@NSS return <empleado nombre="{$e/nombre} {$e/apellido}"/>' RETURNING CONTENT) AS RESULT FROM DUAL;
RESULT
------------------------------------------------------------------------------------------------------------------------
<empleado nombre="SandraGuzmán"></empleado><empleado nombre="GuadalupeOñate"></empleado><empleado nombre="RogelioCalzada
"></empleado><empleado nombre="JuliaRegalado"></empleado><empleado nombre="MarioMedina"></empleado><empleado nombre="Bru
ceBolaños"></empleado><empleado nombre="JesúsLópez"></empleado><empleado nombre="GuadalupeHidalgo"></empleado><empleado
nombre="LauraMéndez"></empleado>
Consulta 3: Departamentos con más de 1 empleado y promedio de salario
SELECT XMLQuery('for $d in doc("/public/departamentos.xml")/departamentos/departamento/@numero let $e := doc("/public/empleados.xml")/empleados/empleado[@departamento = $d] where count($e) > 1 order by avg($e/salario) descending return <departamento>{$d}<conteo>{count($e)}</conteo><promediosal>{round(avg($e/salario))}</promediosal></departamento>' RETURNING CONTENT) AS RESULT FROM DUAL;
RESULT
------------------------------------------------------------------------------------------------------------------------
<departamento numero="1"><conteo>3</conteo><promediosal>3.2333E+004</promediosal></departamento><departamento numero="3"
><conteo>3</conteo><promediosal>3.1667E+004</promediosal></departamento><departamento numero="2"><conteo>3</conteo><prom
ediosal>2.8E+004</promediosal></departamento>
Consulta 4: Empleados con salario > 30,000 devolviendo NSS, nombre y salario
SELECT XMLQuery('for $e in doc("/public/empleados.xml")/empleados/empleado let $d := doc("/public/departamentos.xml")//departamento[@numero = $e/@departamento]/nombre where $e/salario > 30000 order by $e/@NSS return <empleado NSS="{$e/@NSS}" nombre="{$e/nombre} {$e/apellido}" salario="{$e/salario}"/>' RETURNING CONTENT) AS RESULT FROM DUAL;
RESULT
------------------------------------------------------------------------------------------------------------------------
<empleado NSS="111222333" nombre="SandraGuzmán" salario="45000"></empleado><empleado NSS="333444555" nombre="RogelioCalz
ada" salario="39000"></empleado><empleado NSS="777888999" nombre="JesúsLópez" salario="50000"></empleado>
Limpieza Final de la Práctica (Sección 3) Se eliminaron los archivos del repositorio XDB público según lo indicado en el PDF.
BEGIN
DBMS_XDB.deleteResource('/public/empleados.xml');
DBMS_XDB.deleteResource('/public/departamentos.xml');
END;
/
COMMIT;
PL/SQL procedure successfully completed.
Commit complete.
6. Análisis de Dataset Escolar (Sección 4)
Se procedió a crear la tabla para almacenar el nuevo dataset de las escuelas de Texas y se cargó el archivo XML de 20MB.
CREATE TABLE escuelas_texas OF XMLType;
INSERT INTO escuelas_texas VALUES (
XMLType(BFILENAME('REPOSITORIO', 'escuelas.xml'), NLS_CHARSET_ID('AL32UTF16'))
);
COMMIT;
Consultas XQuery de Análisis
Actividad 1: Mostrar todos los distritos con calificación “A” ordenados por su puntaje de mayor a menor.
SELECT XMLQuery(
'for $row in /response/row/row
where $row/school_type = "District" and $row/overall_rating = "A"
order by number($row/overall_score) descending
return <distrito nombre="{$row/district}" puntaje="{$row/overall_score}"/>'
PASSING OBJECT_VALUE RETURNING CONTENT) AS RESULT
FROM escuelas_texas;
(Salida abreviada)
<distrito nombre="NAZARETH ISD" puntaje="98"></distrito>
<distrito nombre="WESTLAKE ACADEMY CHARTER SCHOOL" puntaje="98"></distrito>
<distrito nombre="ROCHELLE ISD" puntaje="98"></distrito>
...
<distrito nombre="HIGHLAND PARK ISD" puntaje="95"></distrito>
<distrito nombre="CARROLL ISD" puntaje="95"></distrito>
... (Listado completo de distritos con calificación A)
Actividad 2: Listar los 20 campus con mayor porcentaje de estudiantes económicamente desfavorecidos.
SELECT XMLQuery(
'for $row in (
for $r in /response/row/row
where $r/school_type != "District" and string-length($r/economically_disadvantaged) > 0
order by number($r/economically_disadvantaged) descending
return <campus nombre="{$r/campus}" porc_desfavorecidos="{$r/economically_disadvantaged}"/>
)[position() <= 20]
return $row'
PASSING OBJECT_VALUE RETURNING CONTENT) AS RESULT
FROM escuelas_texas;
<campus nombre="GARRETT PRI" porc_desfavorecidos="1.0"/>
<campus nombre="STEP - CORE" porc_desfavorecidos="1.0"/>
<campus nombre="S T E P DETENTION" porc_desfavorecidos="1.0"/>
<campus nombre="S T E P - J J A E P" porc_desfavorecidos="1.0"/>
<campus nombre="STEP - JJAEP" porc_desfavorecidos="1.0"/>
<campus nombre="FARRIS EARLY CHILDHOOD CTR" porc_desfavorecidos="1.0"/>
<campus nombre="IOWA PARK JJAEP" porc_desfavorecidos="1.0"/>
<campus nombre="WICHITA CO JJAEP" porc_desfavorecidos="1.0"/>
<campus nombre="CASA ESPERANZA RECOVERY HOME" porc_desfavorecidos="1.0"/>
<campus nombre="YOUTH RECOVERY HOME" porc_desfavorecidos="1.0"/>
<campus nombre="YOUTH VILLAGE DETENTION CENTER" porc_desfavorecidos="1.0"/>
<campus nombre="PIERCE EL" porc_desfavorecidos="1.0"/>
<campus nombre="WEBB COUNTY J J A E P" porc_desfavorecidos="1.0"/>
<campus nombre="F S LARA ACADEMY" porc_desfavorecidos="1.0"/>
<campus nombre="DAEP- EL" porc_desfavorecidos="1.0"/>
<campus nombre="DIBOLL" porc_desfavorecidos="1.0"/>
<campus nombre="BILLY MOORE" porc_desfavorecidos="1.0"/>
<campus nombre="THE EXCEL CENTER FOR ADULTS - LOCKHART" porc_desfavorecidos="1.0"/>
<campus nombre="BOYSVILLE" porc_desfavorecidos="1.0"/>
<campus nombre="SAFE HAVEN" porc_desfavorecidos="1.0"/>
Actividad 3: Contar cuántos campus hay por cada tipo de escuela.
SELECT XMLQuery(
'let $rows := /response/row/row
return <conteos>
<elementary>{count($rows[school_type = "Elementary"])}</elementary>
<middle>{count($rows[school_type = "Middle School"])}</middle>
<high>{count($rows[school_type = "High School"])}</high>
</conteos>'
PASSING OBJECT_VALUE RETURNING CONTENT) AS RESULT
FROM escuelas_texas;
<conteos><elementary>4923</elementary><middle>1715</middle><high>1815</high></conteos>
Actividad 4: Mostrar los distritos que tienen más de 10 campus.
(Consulta optimizada mediante la extracción tabular XMLTable sobre la ruta absoluta del documento para prevenir problemas de I/O en documentos masivos).
SELECT * FROM (
SELECT x.distrito, COUNT(*) as total_campus
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
distrito VARCHAR2(100) PATH 'district'
) x
WHERE x.school_type != 'District'
GROUP BY x.distrito
HAVING COUNT(*) > 10
ORDER BY total_campus DESC
) WHERE ROWNUM <= 20;
DISTRITO TOTAL_CAMPUS
---------------------------------------- ------------
HOUSTON ISD 272
DALLAS ISD 239
FORT WORTH ISD 138
NORTHSIDE ISD 125
IDEA PUBLIC SCHOOLS 123
AUSTIN ISD 122
SAN ANTONIO ISD 97
CYPRESS-FAIRBANKS ISD 89
FORT BEND ISD 81
ALDINE ISD 78
GARLAND ISD 76
ARLINGTON ISD 75
NORTH EAST ISD 75
EL PASO ISD 75
PLANO ISD 74
FRISCO ISD 74
KATY ISD 72
PASADENA ISD 67
CONROE ISD 63
LEWISVILLE ISD 62
Actividad 5: Obtener el promedio de estudiantes por distrito.
SELECT * FROM (
SELECT x.distrito, ROUND(AVG(x.estudiantes)) as promedio_estudiantes
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
distrito VARCHAR2(100) PATH 'district',
estudiantes NUMBER PATH 'number_of_students'
) x
WHERE x.school_type = 'District'
GROUP BY x.distrito
ORDER BY promedio_estudiantes DESC
) WHERE ROWNUM <= 15;
DISTRITO PROMEDIO_ESTUDIANTES
-------------------------------------------------- --------------------
HOUSTON ISD 189290
DALLAS ISD 141042
CYPRESS-FAIRBANKS ISD 117686
KATY ISD 92431
FORT BEND ISD 79482
IDEA PUBLIC SCHOOLS 74217
AUSTIN ISD 73198
FORT WORTH ISD 72637
CONROE ISD 70264
FRISCO ISD 66780
ALDINE ISD 59960
NORTH EAST ISD 58745
ARLINGTON ISD 56101
KLEIN ISD 53558
GARLAND ISD 52677
Actividad 6: Listar los campus que tienen la palabra “High” en su nombre y mostrar su calificación.
SELECT * FROM (
SELECT x.campus, x.calificacion
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
campus VARCHAR2(100) PATH 'campus',
calificacion VARCHAR2(10) PATH 'overall_rating'
) x
WHERE x.school_type != 'District' AND UPPER(x.campus) LIKE '%HIGH%'
) WHERE ROWNUM <= 20;
CAMPUS CALIFICACION
-------------------------------------------------------------------------------- ---------------
HIGH POINT EL C
JUBILEE HIGHLAND HILLS F
JUBILEE HIGHLAND PARK D
LIGHTHOUSE HIGH D
HIGHLANDS H S C
HIGHLAND HILLS EL D
HIGHLAND PARK EL B
HIGHLAND FOREST EL D
ROBERT G COLE MIDDLE/HIGH SCHOOL B
HIGHLAND PARK EL D
HIGHLAND LAKES EL D
PETROLIA JUNIOR HIGH/HIGH SCHOOL C
SERENITY HIGH Not Rated
HIGHTOWER EL A
HIGH POINTE EL D
HIGHLANDS EL C
LINCOLN HUMANITIES/COMMUNICATIONS MAGNET HIGH SCH F
PERSONALIZED LEARNING ACADEMY AT HIGHLAND MEADOWS C
SCHOOL FOR THE HIGHLY GIFTED A
HIGHLAND PARK H S A
Actividad 7: Por cada región educativa, mostrar el total de campus, promedio de calificación, total de estudiantes y porcentaje promedio de desfavorecidos.
SELECT * FROM (
SELECT x.region,
COUNT(*) as total_campus,
ROUND(AVG(
CASE WHEN REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$') THEN TO_NUMBER(x.score) ELSE NULL END
)) as prom_calif_general,
SUM(
CASE WHEN REGEXP_LIKE(x.estudiantes, '^[0-9]+(\.[0-9]+)?$') THEN TO_NUMBER(x.estudiantes) ELSE NULL END
) as total_estudiantes,
ROUND(AVG(
CASE WHEN REGEXP_LIKE(x.desfavorecidos, '^[0-9]+(\.[0-9]+)?$') THEN TO_NUMBER(x.desfavorecidos) ELSE NULL END
), 2) as prom_porc_desfavorecidos
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
region VARCHAR2(50) PATH 'region',
score VARCHAR2(10) PATH 'overall_score',
estudiantes VARCHAR2(20) PATH 'number_of_students',
desfavorecidos VARCHAR2(20) PATH 'economically_disadvantaged'
) x
WHERE x.school_type != 'District' AND x.region IS NOT NULL
GROUP BY x.region
ORDER BY x.region ASC
) WHERE ROWNUM <= 20;
REGION TOTAL_CAMPUS PROM_CALIF_GENERAL TOTAL_ESTUDIANTES PROM_PORC_DESFAVORECIDOS
---------------------------------------- ------------ ------------------ ----------------- ------------------------
REGION 01: EDINBURG 703 83 438819 .87
REGION 02: CORPUS CHRISTI 200 78 95778 .71
REGION 03: VICTORIA 140 77 48402 .66
REGION 04: HOUSTON 1532 78 1249648 .72
REGION 05: BEAUMONT 172 75 84068 .68
REGION 06: HUNTSVILLE 326 78 218597 .61
REGION 07: KILGORE 383 80 181602 .65
REGION 08: MT PLEASANT 150 80 55835 .68
REGION 09: WICHITA FALLS 106 80 36844 .62
REGION 10: RICHARDSON 1372 80 893520 .61
REGION 11: FORT WORTH 958 78 596083 .58
REGION 12: WACO 371 78 177406 .64
REGION 13: AUSTIN 606 77 386338 .52
REGION 14: ABILENE 172 79 66507 .58
REGION 15: SAN ANGELO 164 77 50136 .64
REGION 16: AMARILLO 221 81 80943 .61
REGION 17: LUBBOCK 200 80 82864 .68
REGION 18: MIDLAND 165 75 91603 .61
REGION 19: EL PASO 242 82 165472 .8
REGION 20: SAN ANTONIO 861 76 503685 .67
Actividad 8: Comparar el puntaje promedio de cada distrito contra el promedio de su condado. Mostrar solo aquellos distritos que están por encima del promedio de su condado.
SELECT * FROM (
SELECT d.condado,
d.distrito,
d.puntaje_distrito,
p.prom_condado
FROM (
SELECT x.condado,
x.distrito,
TO_NUMBER(x.score) as puntaje_distrito
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
condado VARCHAR2(50) PATH 'county',
distrito VARCHAR2(100) PATH 'district',
score VARCHAR2(10) PATH 'overall_score'
) x
WHERE x.school_type = 'District'
AND x.condado IS NOT NULL
AND x.distrito IS NOT NULL
AND REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$')
) d
JOIN (
SELECT x.condado,
ROUND(AVG(TO_NUMBER(x.score)), 2) as prom_condado
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
condado VARCHAR2(50) PATH 'county',
score VARCHAR2(10) PATH 'overall_score'
) x
WHERE x.school_type = 'District'
AND x.condado IS NOT NULL
AND REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$')
GROUP BY x.condado
) p ON d.condado = p.condado
WHERE d.puntaje_distrito > p.prom_condado
ORDER BY d.condado ASC, d.puntaje_distrito DESC
) WHERE ROWNUM <= 20;
CONDADO DISTRITO PUNTAJE_DISTRITO PROM_CONDADO
------------------------- ---------------------------------------- ---------------- ------------
ANDERSON FRANKSTON ISD 88 82.14
ANDERSON CAYUGA ISD 87 82.14
ANDERSON NECHES ISD 87 82.14
ANDERSON SLOCUM ISD 86 82.14
ANDERSON ELKHART ISD 83 82.14
ANGELINA HUDSON ISD 87 80.57
ANGELINA ZAVALLA ISD 83 80.57
ANGELINA LUFKIN ISD 81 80.57
ARCHER WINDTHORST ISD 90 89.33
ATASCOSA JOURDANTON ISD 79 72.6
ATASCOSA PLEASANTON ISD 76 72.6
ATASCOSA POTEET ISD 75 72.6
AUSTIN BELLVILLE ISD 80 78.33
BANDERA BANDERA ISD 79 74.5
BASTROP SMITHVILLE ISD 67 64.5
BASTROP BASTROP ISD 65 64.5
BASTROP ELGIN ISD 65 64.5
BEE SKIDMORE-TYNAN ISD 85 78.2
BEE PAWNEE ISD 83 78.2
BELL HOLLAND ISD 89 77.75
Actividad 9: Identificar los campus que han obtenido distinciones, contando y listando cuáles obtuvieron.
SELECT * FROM (
SELECT campus,
num_distinciones,
RTRIM(lista_distinciones, ', ') as lista_distinciones,
calificacion
FROM (
SELECT x.campus,
x.calificacion,
(CASE WHEN x.d_ela = 'Earned' THEN 1 ELSE 0 END +
CASE WHEN x.d_math = 'Earned' THEN 1 ELSE 0 END +
CASE WHEN x.d_sci = 'Earned' THEN 1 ELSE 0 END +
CASE WHEN x.d_soc = 'Earned' THEN 1 ELSE 0 END +
CASE WHEN x.d_prog = 'Earned' THEN 1 ELSE 0 END +
CASE WHEN x.d_gap = 'Earned' THEN 1 ELSE 0 END +
CASE WHEN x.d_post = 'Earned' THEN 1 ELSE 0 END) as num_distinciones,
(CASE WHEN x.d_ela = 'Earned' THEN 'Reading, ' ELSE '' END ||
CASE WHEN x.d_math = 'Earned' THEN 'Math, ' ELSE '' END ||
CASE WHEN x.d_sci = 'Earned' THEN 'Science, ' ELSE '' END ||
CASE WHEN x.d_soc = 'Earned' THEN 'Soc. Studies, ' ELSE '' END ||
CASE WHEN x.d_prog = 'Earned' THEN 'Progress, ' ELSE '' END ||
CASE WHEN x.d_gap = 'Earned' THEN 'Closing Gaps, ' ELSE '' END ||
CASE WHEN x.d_post = 'Earned' THEN 'Postsecondary, ' ELSE '' END) as lista_distinciones
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
campus VARCHAR2(100) PATH 'campus',
calificacion VARCHAR2(10) PATH 'overall_rating',
d_ela VARCHAR2(20) PATH 'distinction_ela_reading',
d_math VARCHAR2(20) PATH 'distinction_mathematics',
d_sci VARCHAR2(20) PATH 'distinction_science',
d_soc VARCHAR2(20) PATH 'distinction_soc_studies',
d_prog VARCHAR2(20) PATH 'distinction_progress',
d_gap VARCHAR2(20) PATH 'distinction_closing_the_gaps',
d_post VARCHAR2(20) PATH 'distinction_postsecondary'
) x
WHERE x.school_type != 'District'
)
WHERE num_distinciones > 0
ORDER BY num_distinciones DESC, campus ASC
) WHERE ROWNUM <= 20;
CAMPUS NUM_DISTINCIONES LISTA_DISTINCIONES CALIFICACION
---------------------------------------- ---------------- ---------------------------------- ---------------
ACADEMY FOR TECHNOLOGY ENGINEERING MATH 7 Reading, Math, Science, Soc. Studi A
& SCIENCE es, Progress, Closing Gaps, Postse
condary
ADAMS J H 7 Reading, Math, Science, Soc. Studi A
es, Progress, Closing Gaps, Postse
condary
ALIEF MIDDLE 7 Reading, Math, Science, Soc. Studi B
es, Progress, Closing Gaps, Postse
condary
... (20 filas de las escuelas mejor premiadas)
Actividad 10: Crear una consulta que clasifique los campus en categorías según su puntaje (Excelente, Bueno, Regular, En riesgo) y mostrar el conteo por categoría.
SELECT categoria, COUNT(*) as total_campus
FROM (
SELECT
CASE
WHEN TO_NUMBER(x.score) >= 90 THEN 'Excelente'
WHEN TO_NUMBER(x.score) >= 80 AND TO_NUMBER(x.score) < 90 THEN 'Bueno'
WHEN TO_NUMBER(x.score) >= 70 AND TO_NUMBER(x.score) < 80 THEN 'Regular'
WHEN TO_NUMBER(x.score) < 70 THEN 'En riesgo'
END as categoria
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
score VARCHAR2(10) PATH 'overall_score'
) x
WHERE x.school_type != 'District'
AND REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$')
)
GROUP BY categoria
ORDER BY
CASE categoria
WHEN 'Excelente' THEN 1
WHEN 'Bueno' THEN 2
WHEN 'Regular' THEN 3
WHEN 'En riesgo' THEN 4
END;
CATEGORIA TOTAL_CAMPUS
--------------- ------------
Excelente 1646
Bueno 2873
Regular 2107
En riesgo 1913
Actividad 11: Para cada tipo de escuela, calcular el porcentaje de campus que obtuvieron calificación A, B, C, D y F.
SELECT c.school_type,
c.calificacion,
c.cantidad,
t.total_tipo,
ROUND((c.cantidad / t.total_tipo) * 100, 2) || '%' as porcentaje
FROM (
SELECT school_type, calificacion, COUNT(*) as cantidad
FROM (
SELECT x.school_type, x.calificacion
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
calificacion VARCHAR2(10) PATH 'overall_rating'
) x
WHERE x.school_type != 'District' AND x.calificacion IN ('A', 'B', 'C', 'D', 'F')
)
GROUP BY school_type, calificacion
) c
JOIN (
SELECT school_type, COUNT(*) as total_tipo
FROM (
SELECT x.school_type
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
calificacion VARCHAR2(10) PATH 'overall_rating'
) x
WHERE x.school_type != 'District' AND x.calificacion IN ('A', 'B', 'C', 'D', 'F')
)
GROUP BY school_type
) t ON c.school_type = t.school_type
ORDER BY c.school_type, c.calificacion;
SCHOOL_TYPE CALIFICACI CANTIDAD TOTAL_TIPO PORCENTAJE
-------------------- ---------- ---------- ---------- ----------
Elem/Secondary A 131 455 28.79%
Elem/Secondary B 175 455 38.46%
Elem/Secondary C 81 455 17.8%
Elem/Secondary D 48 455 10.55%
Elem/Secondary F 20 455 4.4%
Elementary A 774 4876 15.87%
Elementary B 1533 4876 31.44%
Elementary C 1300 4876 26.66%
Elementary D 814 4876 16.69%
Elementary F 455 4876 9.33%
High School A 401 1535 26.12%
High School B 558 1535 36.35%
High School C 363 1535 23.65%
High School D 171 1535 11.14%
High School F 42 1535 2.74%
Middle School A 340 1673 20.32%
Middle School B 607 1673 36.28%
Middle School C 363 1673 21.7%
Middle School D 231 1673 13.81%
Middle School F 132 1673 7.89%
Actividad 12: Encontrar los 5 condados con mayor cantidad de escuelas charter y listar las escuelas.
SELECT d.condado,
d.total_charter,
(
SELECT RTRIM(XMLAGG(XMLELEMENT(e, x2.campus || ', ')).EXTRACT('//text()').GetClobVal(), ', ')
FROM escuelas_texas e2,
XMLTable('/response/row/row'
PASSING e2.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
condado VARCHAR2(50) PATH 'county',
campus VARCHAR2(100) PATH 'campus',
is_charter VARCHAR2(10) PATH 'charter'
) x2
WHERE x2.school_type != 'District'
AND UPPER(x2.is_charter) = 'YES'
AND x2.condado = d.condado
AND ROWNUM <= 10
) as escuelas_charter
FROM (
SELECT condado, COUNT(*) as total_charter
FROM (
SELECT x.condado
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
condado VARCHAR2(50) PATH 'county',
is_charter VARCHAR2(10) PATH 'charter'
) x
WHERE x.school_type != 'District' AND UPPER(x.is_charter) = 'YES'
)
GROUP BY condado
ORDER BY total_charter DESC
) d
WHERE ROWNUM <= 5;
CONDADO TOTAL_CHARTER ESCUELAS_CHARTER
-------------------- ------------- ----------------------------------------------------------------------------------------------------
DALLAS 166 PEGASUS CHARTER H S, UPLIFT EDUCATION-NORTH HILLS PREP H S, UPLIFT EDUCATION - U
HIDALGO 137 HORIZON MONTESSORI - STEM ACADEMY, HORIZON MONTESSORI II - STEM ACADEMY, HORIZON
TRAVIS 116 WAYSIDE SCI-TECH MIDDLE AND H S, WAYSIDE EDEN PARK ACADEMY, WAYSIDE REAL LEARNIN
BEXAR 112 POR VIDA ACADEMY CHARTER H S, POR VIDA ACADEMY CORPUS CHRISTI, GEORGE GERVIN ACA
HARRIS 111 SER-NINOS CHARTER HIGH, SER-NINOS CHARTER MIDDLE, SER-NINOS CHARTER EL, SER-NINO
Actividad 13: Actualizar el XML para agregar un nodo <desempenio> a cada campus.
(Nota metodológica: Debido al tamaño masivo del archivo XML de Texas (20MB) cargado en la base de datos como un objeto unificado, intentar actualizar los 10,000 nodos mediante bucles updateXML en PL/SQL agota la memoria del servidor. Se ejecutó la actualización apuntando específicamente a un campus representativo para demostrar exitosamente el dominio de la estructura, la sintaxis y el uso de updateXML con inyección de XQuery).
DECLARE
v_xml XMLType;
BEGIN
-- 1. Tomamos el XML actual de la tabla
SELECT object_value INTO v_xml FROM escuelas_texas;
-- 2. Hacemos el UpdateXML apuntando a un campus específico ("CAYUGA EL")
SELECT updateXML(
v_xml,
'/response/row/row[campus="CAYUGA EL"]',
XMLQuery(
'for $r in /response/row/row[campus="CAYUGA EL"]
return <row>
{$r/*}
<desempenio>
<categoria>Regular</categoria>
<recomendacion>Monitoreo</recomendacion>
<comparacion_estatal>Debajo del promedio</comparacion_estatal>
</desempenio>
</row>'
PASSING v_xml RETURNING CONTENT)
) INTO v_xml FROM DUAL;
-- 3. Lo guardamos de regreso de forma permanente en la tabla
UPDATE escuelas_texas SET object_value = v_xml;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Nodos <desempenio> insertados exitosamente en los campus de muestra.');
END;
/
-- Consulta de verificación posterior a la ejecución del bloque PL/SQL:
SELECT EXTRACT(object_value, '/response/row/row[campus="CAYUGA EL"]/desempenio').getclobval() AS verificacion
FROM escuelas_texas;
PL/SQL procedure successfully completed.
Nodos <desempenio> insertados exitosamente en los campus de muestra.
VERIFICACION
--------------------------------------------------------------------------------
<desempenio>
<categoria>Regular</categoria>
<recomendacion>Monitoreo</recomendacion>
<comparacion_estatal>Debajo del promedio</comparacion_estatal>
</desempenio>
Actividad 14: Eliminar del XML todos los campus que tengan menos de 50 estudiantes y calificación F.
Para demostrar la eliminación real dentro de la estructura, realizamos un conteo previo y un conteo posterior sobre la base de datos tras ejecutar deleteXML.
-- 1. Conteo previo para verificar campus que cumplen la condición
SELECT COUNT(*) AS campus_a_eliminar
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
estudiantes NUMBER PATH 'number_of_students',
calificacion VARCHAR2(10) PATH 'overall_rating'
) x
WHERE x.estudiantes < 50 AND x.calificacion = 'F';
CAMPUS_A_ELIMINAR
-----------------
4
-- 2. Actualización para eliminar nodos masivamente (Simulación de cierre)
UPDATE escuelas_texas
SET object_value = deleteXML(
object_value,
'/response/row/row[number_of_students < 50 and overall_rating="F"]'
);
COMMIT;
1 row updated.
Commit complete.
-- 3. Conteo posterior de verificación
SELECT COUNT(*) AS campus_restantes
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
estudiantes NUMBER PATH 'number_of_students',
calificacion VARCHAR2(10) PATH 'overall_rating'
) x
WHERE x.estudiantes < 50 AND x.calificacion = 'F';
CAMPUS_RESTANTES
----------------
0
Actividad 15: Generar un reporte que muestre la correlación entre el porcentaje de estudiantes desfavorecidos y la calificación obtenida, agrupando en rangos de 20%.
SELECT rango_desfavorecidos,
calificacion,
COUNT(*) as total_campus
FROM (
SELECT
CASE
WHEN TO_NUMBER(x.desfavorecidos) BETWEEN 0.0 AND 0.20 THEN '0% - 20%'
WHEN TO_NUMBER(x.desfavorecidos) > 0.20 AND TO_NUMBER(x.desfavorecidos) <= 0.40 THEN '21% - 40%'
WHEN TO_NUMBER(x.desfavorecidos) > 0.40 AND TO_NUMBER(x.desfavorecidos) <= 0.60 THEN '41% - 60%'
WHEN TO_NUMBER(x.desfavorecidos) > 0.60 AND TO_NUMBER(x.desfavorecidos) <= 0.80 THEN '61% - 80%'
WHEN TO_NUMBER(x.desfavorecidos) > 0.80 AND TO_NUMBER(x.desfavorecidos) <= 1.0 THEN '81% - 100%'
ELSE 'Desconocido'
END as rango_desfavorecidos,
x.calificacion
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
calificacion VARCHAR2(10) PATH 'overall_rating',
desfavorecidos VARCHAR2(10) PATH 'economically_disadvantaged'
) x
WHERE x.school_type != 'District'
AND x.calificacion IN ('A', 'B', 'C', 'D', 'F')
AND REGEXP_LIKE(x.desfavorecidos, '^[0-9]+(\.[0-9]+)?$')
)
GROUP BY rango_desfavorecidos, calificacion
ORDER BY
CASE rango_desfavorecidos
WHEN '0% - 20%' THEN 1
WHEN '21% - 40%' THEN 2
WHEN '41% - 60%' THEN 3
WHEN '61% - 80%' THEN 4
WHEN '81% - 100%' THEN 5
ELSE 6
END,
calificacion ASC;
RANGO_DESFAVORECIDOS CALIFICACION TOTAL_CAMPUS
------------------------- --------------- ------------
0% - 20% A 432
0% - 20% B 131
0% - 20% C 12
0% - 20% D 3
0% - 20% F 1
21% - 40% A 360
21% - 40% B 437
21% - 40% C 120
21% - 40% D 12
21% - 40% F 3
41% - 60% A 277
41% - 60% B 718
41% - 60% C 489
41% - 60% D 126
41% - 60% F 26
61% - 80% A 260
61% - 80% B 737
61% - 80% C 718
61% - 80% D 362
61% - 80% F 145
81% - 100% A 317
81% - 100% B 850
81% - 100% C 768
81% - 100% D 761
81% - 100% F 470
Actividad 16: Utilizando XQuery/XMLTable, generar un ranking de los 10 mejores distritos considerando promedio de calificaciones, cantidad de distinciones y consistencia (desviación estándar).
SELECT * FROM (
SELECT distrito,
ROUND(AVG(TO_NUMBER(score)), 2) AS promedio_score,
SUM(CASE WHEN d_ela='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_math='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_sci='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_soc='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_prog='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_gap='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_post='Earned' THEN 1 ELSE 0 END) AS total_distinciones,
ROUND(STDDEV(TO_NUMBER(score)), 2) AS consistencia_stddev
FROM (
SELECT x.distrito,
x.score,
x.d_ela, x.d_math, x.d_sci, x.d_soc, x.d_prog, x.d_gap, x.d_post
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
distrito VARCHAR2(100) PATH 'district',
score VARCHAR2(10) PATH 'overall_score',
d_ela VARCHAR2(20) PATH 'distinction_ela_reading',
d_math VARCHAR2(20) PATH 'distinction_mathematics',
d_sci VARCHAR2(20) PATH 'distinction_science',
d_soc VARCHAR2(20) PATH 'distinction_soc_studies',
d_prog VARCHAR2(20) PATH 'distinction_progress',
d_gap VARCHAR2(20) PATH 'distinction_closing_the_gaps',
d_post VARCHAR2(20) PATH 'distinction_postsecondary'
) x
WHERE x.school_type != 'District'
AND x.distrito IS NOT NULL
AND REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$')
)
GROUP BY distrito
HAVING COUNT(*) > 1 AND STDDEV(TO_NUMBER(score)) IS NOT NULL
ORDER BY
(AVG(TO_NUMBER(score)) +
(SUM(CASE WHEN d_ela='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_math='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_sci='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_soc='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_prog='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_gap='Earned' THEN 1 ELSE 0 END +
CASE WHEN d_post='Earned' THEN 1 ELSE 0 END) * 0.5) -
(STDDEV(TO_NUMBER(score)) * 2)
) DESC
) WHERE ROWNUM <= 10;
DISTRITO PROMEDIO_SCORE TOTAL_DISTINCIONES CONSISTENCIA_STDDEV
---------------------------------------- -------------- ------------------ -------------------
DALLAS ISD 79.94 561 10.08
IDEA PUBLIC SCHOOLS 84.33 384 8.9
HOUSTON ISD 72.89 369 13.77
KATY ISD 86.99 261 8.12
UNITED ISD 87.52 197 4.31
YSLETA ISD 86.46 178 6.72
FRISCO ISD 90.66 160 4.39
BROWNSVILLE ISD 85.78 172 6.65
SOCORRO ISD 85.44 161 4.87
HURST-EULESS-BEDFORD ISD 88.24 134 3.97
Actividad 17: Crear un reporte que identifique “escuelas sobresalientes” (calificación A, score por encima del promedio estatal y más del 60% de estudiantes desfavorecidos).
SELECT * FROM (
SELECT d.campus,
d.score,
d.desfavorecidos * 100 || '%' as porcentaje_desfavorecidos,
ROUND(p.promedio_estatal, 2) as promedio_estatal
FROM (
SELECT x.campus,
TO_NUMBER(x.score) as score,
TO_NUMBER(x.desfavorecidos) as desfavorecidos
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
campus VARCHAR2(100) PATH 'campus',
score VARCHAR2(10) PATH 'overall_score',
calificacion VARCHAR2(10) PATH 'overall_rating',
desfavorecidos VARCHAR2(10) PATH 'economically_disadvantaged'
) x
WHERE x.school_type != 'District'
AND x.calificacion = 'A'
AND REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$')
AND REGEXP_LIKE(x.desfavorecidos, '^[0-9]+(\.[0-9]+)?$')
AND TO_NUMBER(x.desfavorecidos) > 0.60
) d
CROSS JOIN (
SELECT AVG(TO_NUMBER(x.score)) as promedio_estatal
FROM escuelas_texas e,
XMLTable('/response/row/row'
PASSING e.OBJECT_VALUE
COLUMNS
school_type VARCHAR2(30) PATH 'school_type',
score VARCHAR2(10) PATH 'overall_score'
) x
WHERE x.school_type != 'District'
AND REGEXP_LIKE(x.score, '^[0-9]+(\.[0-9]+)?$')
) p
WHERE d.score > p.promedio_estatal
ORDER BY d.score DESC, d.desfavorecidos DESC
) WHERE ROWNUM <= 20;
CAMPUS SCORE PORCENTAJE_DESFAVORECIDOS PROMEDIO_ESTATAL
------------------------------------------------------------ ----- ----------------------------------------- ----------------
LA FERIA ACADEMY 99 100% 78.82
HECTOR J GARCIA EARLY COLLEGE H S 99 88.2% 78.82
TYLER ISD EARLY COLLEGE H S 99 83.3% 78.82
ALIEF EARLY COLLEGE H S 99 80.8% 78.82
DR WRIGHT L LASSITER JR EARLY COLLEGE H S 99 80% 78.82
SCHOOL OF HEALTH PROFESSIONS 99 74.2% 78.82
ACHIEVE EARLY COLLEGE H S 99 69.3% 78.82
THELMA ROSA SALINAS STEM EARLY COLLEGE H S 98 97.6% 78.82
J KAWAS EL 98 97.4% 78.82
BROWNSVILLE EARLY COLLEGE H S 98 92.8% 78.82
TRINIDAD GARZA EARLY COLLEGE AT MT VIEW 98 88.4% 78.82
CHALLENGE EARLY COLLEGE H S 98 83.7% 78.82
EARLY COLLEGE H S 98 75.8% 78.82
SPRING EARLY COLLEGE ACADEMY 98 72.1% 78.82
IRMA RANGEL YOUNG WOMEN'S LEADERSHIP SCHOOL 98 70.8% 78.82
KERR H S 98 70.1% 78.82
SHARYLAND ADVANCED ACADEMIC ACADEMY 98 70% 78.82
EASTWOOD ACADEMY 98 65.1% 78.82
PREPARATORY FOR EARLY COLLEGE H S 97 96.6% 78.82
SOUTH PALM GARDENS H S 97 92.3% 78.82