diff --git a/resoluciones/maria-montepeque/ejercicio-84/README.md b/resoluciones/maria-montepeque/ejercicio-84/README.md new file mode 100644 index 00000000..6554eec1 --- /dev/null +++ b/resoluciones/maria-montepeque/ejercicio-84/README.md @@ -0,0 +1,78 @@ +# Ejercicio 84: WHERE Nivel Intermedio + +**Nombre:** Maria Jose Montepeque +**Fecha:** 2026-08-24 + +## Tema central + +WHERE + +## Descripcion del problema + +Una biblioteca tecnica necesita filtros mas elaborados que "mostrar +todo": libros que no son de cierta categoria, prestamos activos +distinguidos de los devueltos, y prestamos de libros que pertenecen a +una categoria especifica, todo combinando varias condiciones a la vez. + +## Tablas y relaciones + +- `autores`: catalogo de autores. +- `libros`: catalogo de libros, cada uno de un autor. +- `prestamos`: tabla principal. `fecha_devolucion` queda en `NULL` + mientras el prestamo sigue activo. `autores` 1—N `libros`; `libros` + 1—N `prestamos`. + +## Uso de WHERE + +En `dql/consultas.sql`: + +1. Negacion y agrupacion: `WHERE categoria <> 'Arquitectura' AND + (ejemplares_totales > 1 OR categoria = 'Algoritmos')` usa + parentesis para controlar el orden en que se evaluan `AND` y `OR`. +2. `IS NULL` / `IS NOT NULL`: distingue prestamos activos de + devueltos, contando cada grupo con subconsultas independientes. +3. Subconsulta dentro de `WHERE ... IN (...)`: primero filtra los + libros de categoria "Arquitectura", y despues usa esa lista de ids + para filtrar los prestamos activos de esos libros especificos. A + diferencia del nivel basico, aqui la condicion de `WHERE` depende + del resultado de otra consulta completa. + +## Otras restricciones aplicadas + +- `PRIMARY KEY` autoincremental en las 3 tablas. +- `FOREIGN KEY`: `libros.id_autor`, `prestamos.id_libro`. +- `NOT NULL` en todas las columnas obligatorias (excepto + `fecha_devolucion`, `NULL` a proposito mientras el prestamo sigue + activo). +- `UNIQUE`: `autores.nombre_autor`. +- `CHECK`: `libros.ejemplares_totales > 0`. +- `DEFAULT` en `prestamos.fecha_prestamo`. +- `PRAGMA foreign_keys = ON;` activado al inicio del script. + +## Caso que falla / no recomendable (comentado en `dql/consultas.sql`) + +`SELECT * FROM libros WHERE (categoria = 'Arquitectura' AND +ejemplares_totales > 1;` falla porque el parentesis que abre antes de +`categoria` nunca se cierra. Se valido con Python (`sqlite3`): lanza +`near ";": syntax error`. + +## Evidencias de ejecucion + +Scripts validados en orden (`ddl` -> `inserts` -> `consultas`) con +Python (modulo `sqlite3`), ya que no se tenia el binario `sqlite3` +disponible en el entorno. Detalle completo en +[`evidencias/resultados.md`](evidencias/resultados.md). + +- Datos finales: 3 autores, 5 libros, 7 prestamos (5 activos, 2 + devueltos). 3 prestamos activos corresponden a libros de + Arquitectura. + +## Como ejecutar + +```bash +sqlite3 ejercicio-84.db < ddl/schema.sql +sqlite3 ejercicio-84.db < dml/inserts.sql +sqlite3 ejercicio-84.db < dql/consultas.sql +``` + +No suba archivos `.db`, `.sqlite` ni `.sqlite3`. diff --git a/resoluciones/maria-montepeque/ejercicio-84/ddl/schema.sql b/resoluciones/maria-montepeque/ejercicio-84/ddl/schema.sql new file mode 100644 index 00000000..947530b2 --- /dev/null +++ b/resoluciones/maria-montepeque/ejercicio-84/ddl/schema.sql @@ -0,0 +1,31 @@ +PRAGMA foreign_keys = ON; + +-- Ejercicio 84: WHERE Nivel Intermedio +-- Tema central: WHERE +-- Contexto: biblioteca tecnica, prestamos de libros. + +CREATE TABLE autores ( + id_autor INTEGER PRIMARY KEY AUTOINCREMENT, + nombre_autor TEXT NOT NULL UNIQUE, + especialidad TEXT NOT NULL +); + +CREATE TABLE libros ( + id_libro INTEGER PRIMARY KEY AUTOINCREMENT, + titulo TEXT NOT NULL, + id_autor INTEGER NOT NULL, + categoria TEXT NOT NULL, + ejemplares_totales INTEGER NOT NULL CHECK (ejemplares_totales > 0), + + FOREIGN KEY (id_autor) REFERENCES autores (id_autor) +); + +CREATE TABLE prestamos ( + id_prestamo INTEGER PRIMARY KEY AUTOINCREMENT, + id_libro INTEGER NOT NULL, + nombre_prestatario TEXT NOT NULL, + fecha_prestamo TEXT NOT NULL DEFAULT (date('now')), + fecha_devolucion TEXT, + + FOREIGN KEY (id_libro) REFERENCES libros (id_libro) +); diff --git a/resoluciones/maria-montepeque/ejercicio-84/dml/inserts.sql b/resoluciones/maria-montepeque/ejercicio-84/dml/inserts.sql new file mode 100644 index 00000000..16527f96 --- /dev/null +++ b/resoluciones/maria-montepeque/ejercicio-84/dml/inserts.sql @@ -0,0 +1,27 @@ +PRAGMA foreign_keys = ON; + +-- Ejercicio 84: WHERE Nivel Intermedio +-- Datos de prueba. + +INSERT INTO autores (nombre_autor, especialidad) VALUES + ('Robert C. Martin', 'Ingenieria de Software'), + ('Donald Knuth', 'Algoritmos'), + ('Martin Fowler', 'Arquitectura de Software'); + +INSERT INTO libros (titulo, id_autor, categoria, ejemplares_totales) VALUES + ('Clean Code', 1, 'Ingenieria', 2), + ('Clean Architecture', 1, 'Arquitectura', 1), + ('The Art of Computer Programming Vol. 1', 2, 'Algoritmos', 1), + ('Refactoring', 3, 'Arquitectura', 3), + ('Patterns of Enterprise Application Architecture', 3, 'Arquitectura', 2); + +INSERT INTO prestamos (id_libro, nombre_prestatario, fecha_prestamo, fecha_devolucion) VALUES + (1, 'Karla Rivas', '2026-08-01', '2026-08-10'), + (4, 'Karla Rivas', '2026-08-04', '2026-08-12'); + +INSERT INTO prestamos (id_libro, nombre_prestatario, fecha_prestamo) VALUES + (1, 'Bryan Solis', '2026-08-05'), + (2, 'Fernanda Lopez', '2026-08-02'), + (3, 'Jorge Cifuentes', '2026-08-03'), + (4, 'Priscila Ajanel', '2026-08-06'), + (5, 'Bryan Solis', '2026-08-07'); diff --git a/resoluciones/maria-montepeque/ejercicio-84/dql/consultas.sql b/resoluciones/maria-montepeque/ejercicio-84/dql/consultas.sql new file mode 100644 index 00000000..bc264c07 --- /dev/null +++ b/resoluciones/maria-montepeque/ejercicio-84/dql/consultas.sql @@ -0,0 +1,46 @@ +.headers on +.mode column + +-- Ejercicio 84: WHERE Nivel Intermedio +-- Consultas de validacion. + +-- 1. Mostrar todos los datos principales. +SELECT p.id_prestamo, l.titulo, a.nombre_autor, p.nombre_prestatario, p.fecha_prestamo +FROM prestamos p +JOIN libros l ON l.id_libro = p.id_libro +JOIN autores a ON a.id_autor = l.id_autor; + +-- 2. WHERE con negacion (<>) y agrupacion con parentesis: libros que +-- NO son de categoria 'Arquitectura', y que ademas tienen mas de un +-- ejemplar. +SELECT titulo, categoria, ejemplares_totales +FROM libros +WHERE categoria <> 'Arquitectura' + AND (ejemplares_totales > 1 OR categoria = 'Algoritmos'); + +-- 3. Consulta con ORDER BY: libros ordenados por cantidad de +-- ejemplares, de mayor a menor. +SELECT titulo, ejemplares_totales +FROM libros +ORDER BY ejemplares_totales DESC; + +-- 4. Conteo o resumen: prestamos activos vs. devueltos, usando +-- IS NULL / IS NOT NULL. +SELECT + (SELECT COUNT(*) FROM prestamos WHERE fecha_devolucion IS NULL) AS activos, + (SELECT COUNT(*) FROM prestamos WHERE fecha_devolucion IS NOT NULL) AS devueltos; + +-- 5. Validacion especifica de WHERE (nivel intermedio: subconsulta +-- dentro de WHERE con IN). Prestamos activos de libros de categoria +-- 'Arquitectura', combinando IS NULL con una subconsulta que primero +-- filtra los libros de esa categoria. +SELECT p.id_prestamo, p.nombre_prestatario, p.fecha_prestamo +FROM prestamos p +WHERE p.fecha_devolucion IS NULL + AND p.id_libro IN ( + SELECT id_libro FROM libros WHERE categoria = 'Arquitectura' + ); + +-- Caso comentado que debe fallar (no ser recomendable), dejar +-- comentado: parentesis sin cerrar en la condicion de WHERE. +-- SELECT * FROM libros WHERE (categoria = 'Arquitectura' AND ejemplares_totales > 1; diff --git a/resoluciones/maria-montepeque/ejercicio-84/evidencias/resultados.md b/resoluciones/maria-montepeque/ejercicio-84/evidencias/resultados.md new file mode 100644 index 00000000..4ac935aa --- /dev/null +++ b/resoluciones/maria-montepeque/ejercicio-84/evidencias/resultados.md @@ -0,0 +1,61 @@ +# Evidencias - Ejercicio 84 + +## Tema + +WHERE + +## Comandos ejecutados + +No se conto con el binario `sqlite3` en el entorno de trabajo, por lo que +la ejecucion se valido con Python (`sqlite3`), aplicando los mismos +scripts en el mismo orden: + +```bash +sqlite3 ejercicio-84.db < ddl/schema.sql +sqlite3 ejercicio-84.db < dml/inserts.sql +sqlite3 ejercicio-84.db < dql/consultas.sql +``` + +## Resultados + +**2. Libros que NO son de Arquitectura, con mas de 1 ejemplar o de +Algoritmos:** + +```text +titulo categoria ejemplares_totales +Clean Code Ingenieria 2 +The Art of Computer Programming Vol. 1 Algoritmos 1 +``` + +**4. Prestamos activos vs. devueltos (`IS NULL` / `IS NOT NULL`):** + +```text +activos devueltos +5 2 +``` + +**5. Prestamos activos de libros de categoria Arquitectura +(subconsulta dentro de `WHERE ... IN`):** + +```text +id_prestamo | nombre_prestatario | fecha_prestamo +4 | Fernanda Lopez | 2026-08-02 +6 | Priscila Ajanel | 2026-08-06 +7 | Bryan Solis | 2026-08-07 +``` + +**Caso comentado verificado:** + +- `SELECT * FROM libros WHERE (categoria = 'Arquitectura' AND ejemplares_totales > 1;` → `near ";": syntax error` (falta el parentesis de cierre). + +## Aprendizaje + +Ademas de `LIKE`, `BETWEEN` y fechas simuladas (nivel basico), este +ejercicio de nivel intermedio demostro `<>` (negacion), agrupacion de +condiciones con parentesis para controlar el orden en que se evaluan +`AND`/`OR`, `IS NULL`/`IS NOT NULL` para distinguir prestamos activos +de devueltos, y una subconsulta dentro de `WHERE ... IN (...)` que +primero filtra los libros de una categoria y despues usa esa lista +para filtrar los prestamos. El caso comentado muestra un error de +sintaxis muy comun: un parentesis que se abre pero nunca se cierra +rompe toda la consulta. diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/README.md b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/README.md new file mode 100644 index 00000000..ddbd9bd2 --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/README.md @@ -0,0 +1,83 @@ +# Solicitud SQL - Ejercicio 084: Estudio Animacion 3D + +**Nombre:** Maria Jose Montepeque +**Fecha:** 2026-08-24 + +## Solicitud del cliente + +Un estudio maneja proyectos de animacion 3D, artistas, entregas y +estados. El cliente necesita un reporte rapido para tomar decisiones +al final de cada semana. Pidio convertir esa operacion en una base de +datos que permita consultar datos, corregir estados, registrar +movimientos y sacar reportes utiles. + +## Que entendi de la solicitud + +"Al final de cada semana" se tradujo en un checkpoint semanal por +proyecto (`entregas`), no solo un estado general del proyecto. Es un +nivel 5 (solicitud profesional): ademas del modelo, se pide +interpretar ambiguedad, normalizar datos, documentar decisiones y +crear al menos una vista SQL. El detalle completo del analisis esta en +[analisis/requerimiento.md](analisis/requerimiento.md). + +## Que tablas cree y por que + +- `clientes`: catalogo de clientes que encargan proyectos. +- `artistas`: catalogo de artistas del estudio. +- `proyectos`: tabla transaccional, cada proyecto de animacion. +- `tareas`: detalle de trabajo especifico de un artista en un + proyecto. +- `entregas`: checkpoint semanal de avance. `UNIQUE (id_proyecto, + semana)` garantiza un solo reporte oficial por semana por proyecto. + +## Vista SQL + +`vista_reporte_semanal` (definida en +[ddl/schema.sql](ddl/schema.sql)) junta entregas, proyecto y cliente +en una sola consulta, respondiendo directamente "que paso esta semana +en cada proyecto". + +## Como se relacionan + +`clientes` 1:N `proyectos`; `proyectos` 1:N `tareas`; `artistas` 1:N +`tareas`; `proyectos` 1:N `entregas`. El diagrama esta en +[diagramas/diagrama-er.svg](diagramas/diagrama-er.svg). + +## Que datos de prueba use + +3 clientes, 4 artistas, 3 proyectos, 8 tareas (incluida una cargada +por error para un alcance que el cliente cancelo) y 4 entregas +semanales (1 sin aprobar todavia). Tambien un `INSERT` comentado que +reproduce el problema de duplicar el checkpoint semanal y debe +fallar. Detalle en [dml/inserts.sql](dml/inserts.sql). + +## Que operaciones de mantenimiento incluyo + +En [dml/operaciones.sql](dml/operaciones.sql): un `DELETE` controlado +que elimina la tarea del alcance cancelado, y un `UPDATE` de estado +(la entrega semanal pendiente se aprueba una vez revisada). + +## Que consultas responden al cliente + +En [dql/consultas.sql](dql/consultas.sql): el reporte semanal completo +usando la vista, en que estado esta cada proyecto, que artista tiene +mas horas trabajadas, las tareas ordenadas por fecha, y un reporte con +`GROUP BY` + `HAVING` de horas totales por proyecto, para decidir +donde reforzar el equipo. + +## Evidencias + +Resultados de ejecutar todo en orden, incluyendo la verificacion del +caso de duplicado y de las operaciones de mantenimiento, en +[evidencias/resultados.md](evidencias/resultados.md). + +## Como ejecutar + +```bash +sqlite3 ejercicio-084.db < ddl/schema.sql +sqlite3 ejercicio-084.db < dml/inserts.sql +sqlite3 ejercicio-084.db < dml/operaciones.sql +sqlite3 ejercicio-084.db < dql/consultas.sql +``` + +No suba archivos `.db`, `.sqlite`, `.sqlite3` ni `.dump`. diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/analisis/requerimiento.md b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/analisis/requerimiento.md new file mode 100644 index 00000000..0ca60a86 --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/analisis/requerimiento.md @@ -0,0 +1,93 @@ +# Analisis del requerimiento - Ejercicio 084 + +## Solicitud entendida + +Un estudio de animacion 3D maneja proyectos, artistas, tareas y +entregas. El cliente necesita un reporte rapido para tomar decisiones +al final de cada semana: eso se traduce en que las entregas del +estudio deben registrarse por semana, para poder consultar de un +vistazo el avance semanal de cada proyecto. Es un nivel 5 (solicitud +profesional): ademas del modelo, se pide interpretar ambiguedad, +normalizar datos, documentar decisiones y crear al menos una vista +SQL. + +## Entidades detectadas + +| Entidad | Por que existe | Atributos importantes | +| --- | --- | --- | +| clientes | Catalogo: cada cliente que encarga un proyecto | nombre_cliente, telefono (unico) | +| artistas | Catalogo: cada artista del estudio | nombre_artista (unico), especialidad | +| proyectos | Tabla transaccional: cada proyecto de animacion | nombre_proyecto, fecha_inicio, estado | +| tareas | Detalle: trabajo especifico de un artista en un proyecto, en una fecha | descripcion, horas_trabajadas | +| entregas | Resultado semanal: checkpoint de avance de un proyecto, uno por semana | semana, fecha_entrega, aprobada | + +## Relaciones detectadas + +| Relacion | Tipo | Explicacion | +| --- | --- | --- | +| clientes -> proyectos | 1:N | Un cliente puede encargar varios proyectos. | +| proyectos -> tareas | 1:N | Un proyecto tiene muchas tareas de distintos artistas. | +| artistas -> tareas | 1:N | Un artista trabaja en muchas tareas distintas. | +| proyectos -> entregas | 1:N | Un proyecto tiene una entrega (checkpoint) por semana. | + +## Decisiones de modelado y ambiguedad interpretada + +- **"Reporte rapido al final de cada semana":** se interpreto como la + necesidad de un checkpoint semanal por proyecto, no solo un estado + general. Por eso `entregas.semana` existe como columna propia, con + `UNIQUE (id_proyecto, semana)`: cada proyecto tiene, como maximo, un + checkpoint oficial por semana, evitando reportes semanales + duplicados o contradictorios. +- **Normalizacion:** las horas trabajadas se registran por tarea + individual (`tareas.horas_trabajadas`), no como un total acumulado + en `proyectos`, para poder sumar y filtrar por artista, por + proyecto o por semana segun lo que necesite el reporte. +- **Vista SQL:** se crea `vista_reporte_semanal`, que junta entregas, + proyecto y cliente en una sola consulta. Responde directamente la + pregunta que trajo el cliente: "que paso esta semana en cada + proyecto". +- **Ambiguedad no resuelta por el cliente:** no se detallo si una + tarea puede registrarse fuera de la semana de su entrega + correspondiente (por ejemplo, trabajo atrasado). Se documenta como + supuesto: las tareas se registran con su propia fecha + (`tareas.fecha_tarea`), independiente de a que entrega semanal + terminen aportando; no se fuerza una relacion directa entre tarea y + entrega en este nivel. + +## Reglas de negocio + +- Regla 1 (relaciones invalidas): todo proyecto debe apuntar a un + cliente real; toda tarea debe apuntar a un proyecto y a un artista + reales; toda entrega debe apuntar a un proyecto real + (`FOREIGN KEY` en cadena). +- Regla 2 (registros repetidos): `clientes.telefono` y + `artistas.nombre_artista` no se repiten (`UNIQUE`); una entrega + semanal no se registra dos veces para el mismo proyecto + (`UNIQUE (id_proyecto, semana)`). +- Regla 3 (valores fuera de rango): `tareas.horas_trabajadas` nunca + negativas; `entregas.semana` siempre 1 o mayor (`CHECK`). +- Regla 4: un proyecto nace `'en_curso'` y avanza a `'pausado'`, + `'finalizado'` o `'cancelado'` (`CHECK`); una entrega nace sin + aprobar (`aprobada = 0`) y se corrige a aprobada con `UPDATE` cuando + el cliente la revisa y la acepta. +- Regla 5: una tarea se puede eliminar con `DELETE` solo cuando fue un + error de captura confirmado (por ejemplo, trabajo registrado para un + alcance que el cliente cancelo). El historico real de tareas no se + borra. + +## Supuestos + +- El cliente no detallo si un artista puede trabajar en varios + proyectos a la vez; se asume que si. +- No se detallo un limite de horas por semana; se asume que ese + control queda fuera del alcance de este nivel. + +## Preguntas que responde la base de datos + +1. Que paso cada semana en cada proyecto (via la vista + `vista_reporte_semanal`). +2. Que proyectos estan en curso, pausados, finalizados o cancelados. +3. Que artista tiene mas horas trabajadas (ranking de actividad). +4. Como se ordenan las tareas por fecha. +5. Que proyecto acumulo mas horas de trabajo, para decidir donde + reforzar el equipo. diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/ddl/schema.sql b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/ddl/schema.sql new file mode 100644 index 00000000..e8f7e69e --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/ddl/schema.sql @@ -0,0 +1,71 @@ +PRAGMA foreign_keys = ON; + +-- Ejercicio 084: Estudio Animacion 3D +-- Modelo: clientes -> proyectos (1:N); proyectos + artistas -> +-- tareas (1:N cada una); proyectos -> entregas (1:N, una por +-- semana). + +CREATE TABLE clientes ( + id_cliente INTEGER PRIMARY KEY AUTOINCREMENT, + nombre_cliente TEXT NOT NULL, + telefono TEXT NOT NULL UNIQUE +); + +CREATE TABLE artistas ( + id_artista INTEGER PRIMARY KEY AUTOINCREMENT, + nombre_artista TEXT NOT NULL UNIQUE, + especialidad TEXT NOT NULL CHECK (especialidad IN ('modelado', 'animacion', 'render', 'texturizado')) +); + +CREATE TABLE proyectos ( + id_proyecto INTEGER PRIMARY KEY AUTOINCREMENT, + id_cliente INTEGER NOT NULL, + nombre_proyecto TEXT NOT NULL, + fecha_inicio TEXT NOT NULL, + estado TEXT NOT NULL DEFAULT 'en_curso' + CHECK (estado IN ('en_curso', 'pausado', 'finalizado', 'cancelado')), + + FOREIGN KEY (id_cliente) REFERENCES clientes (id_cliente) +); + +CREATE TABLE tareas ( + id_tarea INTEGER PRIMARY KEY AUTOINCREMENT, + id_proyecto INTEGER NOT NULL, + id_artista INTEGER NOT NULL, + descripcion TEXT NOT NULL, + fecha_tarea TEXT NOT NULL, + horas_trabajadas REAL NOT NULL CHECK (horas_trabajadas >= 0), + + FOREIGN KEY (id_proyecto) REFERENCES proyectos (id_proyecto), + FOREIGN KEY (id_artista) REFERENCES artistas (id_artista) +); + +-- entregas: el UNIQUE compuesto garantiza como maximo un checkpoint +-- semanal oficial por proyecto, evitando reportes semanales +-- duplicados o contradictorios. +CREATE TABLE entregas ( + id_entrega INTEGER PRIMARY KEY AUTOINCREMENT, + id_proyecto INTEGER NOT NULL, + semana INTEGER NOT NULL CHECK (semana >= 1), + fecha_entrega TEXT NOT NULL, + aprobada INTEGER NOT NULL DEFAULT 0 CHECK (aprobada IN (0, 1)), + + FOREIGN KEY (id_proyecto) REFERENCES proyectos (id_proyecto), + UNIQUE (id_proyecto, semana) +); + +-- Vista SQL (requerida en nivel 5): responde directamente la +-- pregunta del cliente ("que paso esta semana en cada proyecto"), sin +-- repetir el JOIN cada vez. +CREATE VIEW vista_reporte_semanal AS + SELECT + en.id_entrega, + cl.nombre_cliente, + pr.nombre_proyecto, + pr.estado, + en.semana, + en.fecha_entrega, + en.aprobada + FROM entregas en + JOIN proyectos pr ON pr.id_proyecto = en.id_proyecto + JOIN clientes cl ON cl.id_cliente = pr.id_cliente; diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/diagramas/.gitkeep b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/diagramas/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/diagramas/diagrama-er.svg b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/diagramas/diagrama-er.svg new file mode 100644 index 00000000..52df802d --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/diagramas/diagrama-er.svg @@ -0,0 +1,61 @@ + + + + + clientes + id_cliente PK + nombre_cliente + telefono UNIQUE + + + artistas + id_artista PK + nombre_artista UNIQUE + especialidad CHECK + + + proyectos + id_proyecto PK + id_cliente FK + estado CHECK + + + tareas + id_tarea PK + id_proyecto FK, id_artista FK + horas_trabajadas + + + entregas + id_entrega PK + id_proyecto FK + UNIQUE(proyecto, semana) + + + vista_reporte_semanal + JOIN entregas+proyecto+cliente + + + + 1:N + + + + 1:N + + + + 1:N + + + + 1:N + diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dml/inserts.sql b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dml/inserts.sql new file mode 100644 index 00000000..a95334e5 --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dml/inserts.sql @@ -0,0 +1,63 @@ +PRAGMA foreign_keys = ON; + +-- Ejercicio 084: Estudio Animacion 3D +-- Datos base: 3 clientes, 4 artistas, 3 proyectos, 8 tareas (incluye +-- 1 cargada por error para un alcance que el cliente cancelo) y 4 +-- entregas semanales (1 todavia sin aprobar). + +INSERT INTO clientes (nombre_cliente, telefono) VALUES + ('Manuel Estrada', '5555-6201'), + ('Alejandra Chinchilla', '5555-6202'), + ('Byron Xicay', '5555-6203'); + +INSERT INTO artistas (nombre_artista, especialidad) VALUES + ('Karla Rivas', 'modelado'), + ('Bryan Solis', 'animacion'), + ('Fernanda Lopez', 'render'), + ('Jorge Cifuentes', 'texturizado'); + +INSERT INTO proyectos (id_cliente, nombre_proyecto, fecha_inicio, estado) VALUES + (1, 'Serie Aventuras Espaciales', '2026-07-01', 'en_curso'), + (2, 'Comercial Bebida Energetica', '2026-07-15', 'en_curso'), + (3, 'Pelicula Corta Fantasia', '2026-06-01', 'finalizado'); + +-- Tareas del proyecto 1 (Serie Aventuras Espaciales). +INSERT INTO tareas (id_proyecto, id_artista, descripcion, fecha_tarea, horas_trabajadas) VALUES + (1, 1, 'Modelado nave principal', '2026-08-01', 8), + (1, 2, 'Animacion despegue', '2026-08-02', 6), + (1, 3, 'Render escena 1', '2026-08-03', 10); + +-- Tareas del proyecto 2 (Comercial Bebida Energetica). +INSERT INTO tareas (id_proyecto, id_artista, descripcion, fecha_tarea, horas_trabajadas) VALUES + (2, 2, 'Animacion logo', '2026-08-01', 4), + (2, 4, 'Texturizado lata', '2026-08-02', 5); + +-- Tareas del proyecto 3 (Pelicula Corta Fantasia, ya finalizado). +INSERT INTO tareas (id_proyecto, id_artista, descripcion, fecha_tarea, horas_trabajadas) VALUES + (3, 1, 'Modelado personaje final', '2026-07-20', 12), + (3, 3, 'Render final', '2026-07-25', 15); + +-- Tarea cargada por error: el cliente del proyecto 2 cancelo un +-- alcance extra (etiqueta adicional) despues de que ya se habia +-- registrado el trabajo. Se corrige con DELETE en +-- dml/operaciones.sql. +INSERT INTO tareas (id_proyecto, id_artista, descripcion, fecha_tarea, horas_trabajadas) VALUES + (2, 4, 'Texturizado etiqueta extra (alcance cancelado)', '2026-08-03', 3); + +-- Entregas semanales. +INSERT INTO entregas (id_proyecto, semana, fecha_entrega, aprobada) VALUES + (1, 1, '2026-08-07', 1), + (2, 1, '2026-08-07', 1), + (3, 5, '2026-07-30', 1); + +-- Entrega de la semana 2 del proyecto 1, todavia pendiente de +-- revision del cliente. Se aprueba con UPDATE en +-- dml/operaciones.sql. +INSERT INTO entregas (id_proyecto, semana, fecha_entrega, aprobada) VALUES + (1, 2, '2026-08-14', 0); + +-- Caso comentado que debe fallar (queda comentado): registrar una +-- segunda entrega para la semana 1 del proyecto 1, exactamente el +-- problema de reportes semanales duplicados que este UNIQUE esta +-- disenado para evitar. +-- INSERT INTO entregas (id_proyecto, semana, fecha_entrega) VALUES (1, 1, '2026-08-08'); diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dml/operaciones.sql b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dml/operaciones.sql new file mode 100644 index 00000000..34012a1b --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dml/operaciones.sql @@ -0,0 +1,22 @@ +PRAGMA foreign_keys = ON; + +-- Ejercicio 084: Estudio Animacion 3D +-- Operaciones de mantenimiento sobre los datos base. + +-- 1 DELETE controlado: se confirma que el alcance extra del proyecto +-- 2 (etiqueta adicional) fue cancelado por el cliente; la tarea que +-- ya se habia registrado por ese trabajo se elimina. +DELETE FROM tareas +WHERE id_proyecto = 2 AND descripcion = 'Texturizado etiqueta extra (alcance cancelado)'; + +-- 1 UPDATE de estado: el cliente revisa y aprueba la entrega de la +-- semana 2 del proyecto 1. +UPDATE entregas +SET aprobada = 1 +WHERE id_proyecto = 1 AND semana = 2 AND aprobada = 0; + +-- Caso que debe fallar / no ser recomendable (queda comentado): +-- borrar una tarea real ya confirmada (no un error de captura), por +-- ejemplo el modelado de la nave principal. El historico real de +-- tareas no se borra. +-- DELETE FROM tareas WHERE id_proyecto = 1 AND descripcion = 'Modelado nave principal'; diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dql/consultas.sql b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dql/consultas.sql new file mode 100644 index 00000000..cff6739d --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/dql/consultas.sql @@ -0,0 +1,39 @@ +.headers on +.mode column + +-- Ejercicio 084: Estudio Animacion 3D +-- Consultas que responden preguntas reales del cliente. + +-- 1. Que registros principales existen: se usa la vista +-- vista_reporte_semanal (creada en ddl/schema.sql), el reporte rapido +-- que pidio el cliente para cada semana de cada proyecto. +SELECT * +FROM vista_reporte_semanal; + +-- 2. Que proyectos estan en curso, pausados, finalizados o +-- cancelados. +SELECT id_proyecto, nombre_proyecto, estado +FROM proyectos +ORDER BY estado; + +-- 3. Que artista tiene mas horas trabajadas (ranking de actividad). +SELECT a.nombre_artista, SUM(t.horas_trabajadas) AS horas_totales +FROM artistas a +JOIN tareas t ON t.id_artista = a.id_artista +GROUP BY a.id_artista, a.nombre_artista +ORDER BY horas_totales DESC, a.nombre_artista; + +-- 4. Tareas ordenadas por fecha. +SELECT id_tarea, fecha_tarea, horas_trabajadas +FROM tareas +ORDER BY fecha_tarea; + +-- 5. Reporte para decision de negocio: horas totales por proyecto, +-- para decidir donde reforzar el equipo (GROUP BY + HAVING). +SELECT pr.nombre_proyecto, + SUM(t.horas_trabajadas) AS horas_totales +FROM tareas t +JOIN proyectos pr ON pr.id_proyecto = t.id_proyecto +GROUP BY pr.id_proyecto, pr.nombre_proyecto +HAVING SUM(t.horas_trabajadas) > 0 +ORDER BY horas_totales DESC; diff --git a/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/evidencias/resultados.md b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/evidencias/resultados.md new file mode 100644 index 00000000..010facd0 --- /dev/null +++ b/resoluciones/maria-montepeque/solicitudes-sql/ejercicio-084/evidencias/resultados.md @@ -0,0 +1,74 @@ +# Evidencias - Solicitudes SQL - Ejercicio 084 (Estudio Animacion 3D) + +## Comandos ejecutados + +No se conto con el binario `sqlite3` en el entorno de trabajo, por lo que +la ejecucion se valido con Python (`sqlite3`), aplicando los mismos +scripts en el mismo orden: + +```bash +sqlite3 ejercicio-084.db < ddl/schema.sql +sqlite3 ejercicio-084.db < dml/inserts.sql +sqlite3 ejercicio-084.db < dml/operaciones.sql +sqlite3 ejercicio-084.db < dql/consultas.sql +``` + +## Resultados + +Datos base tras `dml/inserts.sql`: 3 clientes, 4 artistas, 3 +proyectos, 8 tareas (incluye la cargada por error para el alcance +cancelado) y 4 entregas semanales (1 sin aprobar todavia). + +**Caso comentado verificado:** + +- `INSERT INTO entregas (id_proyecto, semana, ...) VALUES (1, 1, ...);` (segunda entrega para la semana 1 del proyecto 1) → `UNIQUE constraint failed: entregas.id_proyecto, entregas.semana`. + +**1. Reporte rapido semanal via `vista_reporte_semanal` (ya con la +entrega de la semana 2 del proyecto 1 aprobada):** + +```text +id_entrega | nombre_cliente | nombre_proyecto | estado | semana | fecha_entrega | aprobada +1 | Manuel Estrada | Serie Aventuras Espaciales | en_curso | 1 | 2026-08-07 | 1 +2 | Alejandra Chinchilla | Comercial Bebida Energetica | en_curso | 1 | 2026-08-07 | 1 +3 | Byron Xicay | Pelicula Corta Fantasia | finalizado | 5 | 2026-07-30 | 1 +4 | Manuel Estrada | Serie Aventuras Espaciales | en_curso | 2 | 2026-08-14 | 1 +``` + +**3. Artista con mas horas trabajadas:** + +```text +nombre_artista horas_totales +Fernanda Lopez 25.0 +Karla Rivas 20.0 +Bryan Solis 10.0 +Jorge Cifuentes 5.0 +``` + +**5. Horas totales por proyecto (para decidir donde reforzar el +equipo):** + +```text +nombre_proyecto horas_totales +Pelicula Corta Fantasia 27.0 +Serie Aventuras Espaciales 24.0 +Comercial Bebida Energetica 9.0 +``` + +(El proyecto de la bebida energetica quedo con solo 9 horas porque la +tarea del alcance cancelado, 3 horas, ya se elimino.) + +## Operaciones de mantenimiento verificadas + +- **DELETE controlado**: se elimino la tarea del alcance extra que el cliente cancelo (proyecto 2). Total de tareas: 8 -> 7. +- `UPDATE entregas SET aprobada = 1 WHERE id_proyecto = 1 AND semana = 2 ...;` → el cliente reviso y aprobo la entrega de la semana 2 del proyecto 1. + +## Aprendizaje + +El `UNIQUE (id_proyecto, semana)` en `entregas` garantiza que el +reporte semanal que pidio el cliente sea siempre confiable: nunca +habra dos checkpoints oficiales para la misma semana del mismo +proyecto. La vista `vista_reporte_semanal` responde directamente "que +paso esta semana en cada proyecto", que era exactamente la necesidad +de la solicitud original. El `DELETE` controlado solo corrige tareas +de un alcance que el cliente confirmo que se cancelo; el historico +real de trabajo nunca se borra.