# Material del Curso de SQL — dataconalex

Base de datos de práctica que usamos a lo largo de **todo** el curso, básico e intermedio.
Motor: **Microsoft SQL Server** (2016 o superior). Funciona en SQL Server Express, que es gratuito.

---

## Instalación

**Opción rápida (recomendada):**
1. Abre SQL Server Management Studio (SSMS) o Azure Data Studio.
2. Abre el archivo `00_instalacion_completa.sql`.
3. Ejecútalo completo (F5). Listo.

**Opción por pasos:**
1. Ejecuta `01_crear_tablas.sql` — crea la base `CursoSQL` y las 7 tablas.
2. Ejecuta `02_insertar_datos.sql` — carga los datos.

Al final verás un conteo de filas por tabla. Debe coincidir con esto:

| Tabla | Filas |
|---|---|
| categorias | 8 |
| sucursales | 5 |
| empleados | 20 |
| clientes | 60 |
| productos | 40 |
| ventas | 240 |
| detalle_ventas | 500 |

Si algo no coincide, vuelve a correr `00_instalacion_completa.sql` desde cero.

---

## El negocio

Una cadena de tiendas minoristas con 5 sucursales en México. Vende electrónica, ropa,
hogar, deportes, juguetes, libros, belleza y alimentos.

## Modelo de datos

```
categorias                sucursales
    |                        |    |
    |                        |    |
productos              empleados  |
    |                    |  |  |  |
    |                    |  +--+  |     <- jefe_id apunta a la misma tabla
    |                    |        |
    |                  ventas <---+
    |                    |
    +--- detalle_ventas -+
              |
          clientes ------+
```

### Relaciones

| Desde | Hacia | Llave |
|---|---|---|
| productos | categorias | categoria_id |
| empleados | sucursales | sucursal_id |
| empleados | empleados | jefe_id → empleado_id |
| clientes | — | (no depende de nadie) |
| ventas | clientes | cliente_id |
| ventas | empleados | empleado_id |
| ventas | sucursales | sucursal_id |
| detalle_ventas | ventas | venta_id |
| detalle_ventas | productos | producto_id |

### Granularidad (importante)

- Una fila de **`ventas`** = un ticket.
- Una fila de **`detalle_ventas`** = un producto dentro de ese ticket.

Un ticket puede tener entre 1 y 4 productos. Por eso, al hacer JOIN entre `ventas` y
`detalle_ventas`, las filas de `ventas` se duplican. Eso no es un error: es cómo funcionan
los JOINs, y lo vemos a detalle en su propio video.

---

## Diccionario de datos

### `categorias`
| Columna | Tipo | Notas |
|---|---|---|
| categoria_id | INT | PK |
| nombre_categoria | NVARCHAR(50) | |
| descripcion | NVARCHAR(200) | admite NULL |

### `sucursales`
| Columna | Tipo | Notas |
|---|---|---|
| sucursal_id | INT | PK |
| nombre_sucursal | NVARCHAR(60) | |
| ciudad | NVARCHAR(60) | |
| estado | NVARCHAR(60) | |
| fecha_apertura | DATE | |

### `empleados`
| Columna | Tipo | Notas |
|---|---|---|
| empleado_id | INT | PK |
| nombre | NVARCHAR(50) | |
| apellido | NVARCHAR(50) | |
| puesto | NVARCHAR(40) | Director General, Gerente, Vendedor, Almacenista, Analista |
| jefe_id | INT | FK a `empleados`, NULL solo para el Director |
| sucursal_id | INT | FK a `sucursales` |
| fecha_contratacion | DATE | |
| salario | DECIMAL(10,2) | mensual |
| activo | BIT | 1 = activo, 0 = baja |

### `clientes`
| Columna | Tipo | Notas |
|---|---|---|
| cliente_id | INT | PK |
| nombre | NVARCHAR(50) | |
| apellido | NVARCHAR(50) | |
| email | NVARCHAR(100) | admite NULL |
| telefono | NVARCHAR(20) | admite NULL |
| ciudad | NVARCHAR(60) | |
| estado | NVARCHAR(60) | |
| fecha_registro | DATE | |
| segmento | NVARCHAR(20) | Nuevo, Frecuente, VIP |

### `productos`
| Columna | Tipo | Notas |
|---|---|---|
| producto_id | INT | PK |
| nombre_producto | NVARCHAR(80) | |
| categoria_id | INT | FK a `categorias` |
| precio_unitario | DECIMAL(10,2) | precio de venta |
| costo_unitario | DECIMAL(10,2) | costo; sirve para calcular margen |
| stock | INT | puede ser 0 |
| activo | BIT | 1 = a la venta, 0 = descontinuado |
| fecha_alta | DATE | |

### `ventas`
| Columna | Tipo | Notas |
|---|---|---|
| venta_id | INT | PK |
| cliente_id | INT | FK a `clientes` |
| empleado_id | INT | FK a `empleados` |
| sucursal_id | INT | FK a `sucursales` |
| fecha_venta | DATE | del 2024-01-01 al 2025-12-31 |
| metodo_pago | NVARCHAR(30) | Efectivo, Tarjeta de Crédito, Tarjeta de Débito, Transferencia |
| estatus | NVARCHAR(20) | Completada, Cancelada, Pendiente |

### `detalle_ventas`
| Columna | Tipo | Notas |
|---|---|---|
| detalle_id | INT | PK |
| venta_id | INT | FK a `ventas` |
| producto_id | INT | FK a `productos` |
| cantidad | INT | de 1 a 5 |
| precio_unitario | DECIMAL(10,2) | precio al momento de la venta |
| descuento | DECIMAL(4,2) | fracción (0.10 = 10%), admite NULL |

Para calcular el importe de una línea:
`cantidad * precio_unitario * (1 - COALESCE(descuento, 0))`

---

## Cosas puestas a propósito

Estos "defectos" no son errores del archivo. Están ahí porque cada uno es la excusa
perfecta para un tema del curso:

| Qué hay en los datos | Para qué tema sirve |
|---|---|
| 6 clientes sin email, 9 sin teléfono | IS NULL, COALESCE |
| 354 líneas de venta sin descuento (NULL) | por qué `SUM` ignora NULL y `= NULL` no funciona |
| 10 clientes que nunca han comprado | LEFT JOIN vs INNER JOIN |
| 5 productos que nunca se vendieron | LEFT JOIN desde `productos` |
| 4 nombres de cliente con espacios o mayúsculas raras | TRIM, UPPER, LOWER |
| `jefe_id` NULL solo en el Director | SELF JOIN, IS NULL |
| Ventas Canceladas y Pendientes | WHERE, CASE WHEN, "no toda venta cuenta" |
| Productos con `activo = 0` y `stock = 0` | filtros con BIT, HAVING |
| 2 años completos de fechas | funciones de fecha, acumulados, LAG/LEAD |
| Una categoría con `descripcion` NULL | JOIN + NULL en columnas de texto |

---

## Preguntas de práctica

Si ya quieres adelantarte, intenta responder estas con puro SQL:

**Nivel básico**
1. ¿Cuántos clientes hay por estado?
2. ¿Cuáles son los 5 productos más caros?
3. ¿Cuántas ventas hizo cada sucursal en 2025?
4. ¿Qué empleados ganan más de 20,000?
5. ¿Qué clientes no tienen teléfono registrado?
6. ¿Cuántas ventas hay por método de pago, ordenadas de mayor a menor?
7. ¿Qué categorías tienen más de 5 productos?

**Nivel intermedio**
8. ¿Cuál es el ingreso total por categoría, contando solo ventas Completadas?
9. ¿Qué clientes nunca han comprado nada?
10. ¿Quién es el jefe de cada empleado? (nombre completo, no el id)
11. ¿Cuál es el ticket promedio por sucursal?
12. ¿Cuál fue el mes con mayor venta de cada año?
13. Ranking de vendedores por ingreso generado dentro de su propia sucursal.
14. Ingreso acumulado mes a mes a lo largo de los 2 años.
15. ¿Cuánto creció o cayó la venta de cada mes contra el mes anterior?

Las resolvemos en los videos.
