Nivel Intermedio: Dominando SQL

Has superado los fundamentos. Es hora de profundizar en técnicas avanzadas que te permitirán optimizar consultas, manejar datos complejos y construir soluciones robustas en SQL Server.

Módulo 1: Funciones Avanzadas y Procesamiento de Datos

Las funciones son herramientas poderosas que transforman y analizan tus datos directamente en las consultas, evitando procesamiento manual.

Lección 1.1: Funciones de cadena (LEN, SUBSTRING, REPLACE)

Las funciones de cadena te permiten manipular texto. LEN() obtiene la longitud, SUBSTRING() extrae parte del texto, y REPLACE() sustituye caracteres.

-- Obtener la longitud del nombre del cliente SELECT Nombre, LEN(Nombre) AS LongitudNombre FROM Clientes; -- Extraer los primeros 3 caracteres del código postal SELECT CodigoPostal, SUBSTRING(CodigoPostal, 1, 3) AS Prefijo FROM Direcciones; -- Reemplazar 'Sr.' por 'Señor' en los títulos SELECT REPLACE(Titulo, 'Sr.', 'Señor') AS TituloCompleto FROM Empleados;

Lección 1.2: Funciones de fecha (GETDATE, DATEADD, DATEDIFF)

Trabajar con fechas es común. GETDATE() obtiene la fecha actual, DATEADD() suma/resta tiempo, y DATEDIFF() calcula la diferencia entre fechas.

-- Fecha y hora actual del sistema SELECT GETDATE() AS FechaActual; -- Pedidos realizados hace exactamente 30 días SELECT * FROM Pedidos WHERE FechaPedido = DATEADD(DAY, -30, GETDATE()); -- Días transcurridos desde cada pedido SELECT PedidoID, DATEDIFF(DAY, FechaPedido, GETDATE()) AS DiasTranscurridos FROM Pedidos;

Lección 1.3: Funciones matemáticas (ROUND, CEILING, FLOOR)

Redondean números según tus necesidades. ROUND() redondea al entero más cercano o a decimales específicos, CEILING() redondea siempre hacia arriba, y FLOOR() hacia abajo.

-- Redondear precios a 2 decimales SELECT Producto, Precio, ROUND(Precio, 2) AS PrecioRedondeado FROM Productos; -- Obtener el número de empleados redondeado hacia arriba SELECT CEILING(AVG(Edad)) AS EdadPromedioRedondeada FROM Empleados;

Lección 1.4: CASE WHEN para lógica condicional

CASE WHEN es como un "if-else" dentro de SQL. Te permite crear nuevas columnas basadas en condiciones.

-- Clasificar clientes por nivel de gasto SELECT ClienteID, Nombre, CASE WHEN TotalCompras > 5000 THEN 'VIP' WHEN TotalCompras > 1000 THEN 'Regular' ELSE 'Nuevo' END AS CategoriaCliente FROM Clientes;
Pro Tip: Usa funciones en la cláusula SELECT para transformar datos sin modificar la tabla original. Esto mantiene la integridad de tus datos fuente.

Ejercicios de Práctica del Módulo 1

  1. Escribe una consulta que muestre el nombre completo de los empleados en mayúsculas y cuente cuántos caracteres tiene cada nombre.
  2. Muestra todos los pedidos con su fecha original y la fecha con 7 días adicionales para estimar entrega.
  3. Crea una columna calculada que clasifique los productos como 'Caro' (precio > 100), 'Medio' (50-100) o 'Barato' (< 50).
  4. Calcula cuántos meses han pasado desde la contratación de cada empleado hasta hoy.
  5. Redondea todos los salarios de la tabla Empleados al múltiplo de 100 más cercano.

Módulo 2: Agregación y Análisis de Datos

Transforma filas individuales en información resumida y significativa con funciones de agregación.

Lección 2.1: GROUP BY y funciones de agregación (COUNT, SUM, AVG, MIN, MAX)

GROUP BY agrupa filas con valores idénticos. Las funciones de agregación calculan valores totales por grupo.

-- Total de ventas por cliente SELECT ClienteID, COUNT(*) AS TotalPedidos, SUM(Total) AS TotalVentas FROM Pedidos GROUP BY ClienteID;

Lección 2.2: HAVING para filtrar grupos

HAVING filtra grupos después de que se han calculado las agregaciones (a diferencia de WHERE que filtra filas individuales).

-- Clientes que han gastado más de 1000€ SELECT ClienteID, SUM(Total) AS TotalGastado FROM Pedidos GROUP BY ClienteID HAVING SUM(Total) > 1000;

Lección 2.3: Ordenamiento de resultados agregados

Puedes ordenar los resultados agrupados por las columnas calculadas.

-- Top 5 clientes con mayor gasto SELECT TOP 5 ClienteID, SUM(Total) AS TotalGastado FROM Pedidos GROUP BY ClienteID ORDER BY TotalGastado DESC;

Lección 2.4: ROLLUP y CUBE para subtotales

ROLLUP genera subtotales y un gran total. CUBE genera todos los posibles subtotales.

-- Ventas por año y mes con subtotales SELECT Año, Mes, SUM(Ventas) AS TotalVentas FROM ReporteVentas GROUP BY ROLLUP(Año, Mes);

Ejercicios de Práctica del Módulo 2

  1. Calcula el número de productos y el precio promedio por categoría.
  2. Encuentra las categorías que tienen más de 10 productos y ordena por cantidad descendente.
  3. Muestra el empleado que ha realizado más ventas este mes.
  4. Crea un reporte con el total vendido por día de la semana.
  5. Utiliza ROLLUP para mostrar ventas por país, región y ciudad con subtotales.

Módulo 3: Subconsultas y Consultas Anidadas

Las subconsultas permiten realizar cálculos complejos en pasos separados, haciendo tus consultas más potentes y flexibles.

Lección 3.1: Subconsultas en la cláusula WHERE (IN, EXISTS)

Usa el resultado de una consulta para filtrar otra. IN comprueba pertenencia, EXISTS verifica si existe al menos un resultado.

-- Clientes que han hecho pedidos SELECT * FROM Clientes WHERE ClienteID IN (SELECT DISTINCT ClienteID FROM Pedidos); -- Productos que nunca se han vendido SELECT * FROM Productos WHERE NOT EXISTS (SELECT 1 FROM DetallesPedido WHERE ProductoID = Productos.ProductoID);

Lección 3.2: Subconsultas en FROM (tablas derivadas)

Puedes usar el resultado de una consulta como si fuera una tabla temporal.

-- Promedio de ventas por cliente SELECT AVG(TotalVentas) AS PromedioVentas FROM ( SELECT ClienteID, SUM(Total) AS TotalVentas FROM Pedidos GROUP BY ClienteID ) AS VentasPorCliente;

Lección 3.3: Subconsultas escalares en SELECT

Una subconsulta escalar devuelve un solo valor y puede usarse como una columna calculada.

-- Clientes con su última fecha de pedido SELECT Nombre, (SELECT MAX(FechaPedido) FROM Pedidos WHERE Pedidos.ClienteID = Clientes.ClienteID) AS UltimoPedido FROM Clientes;

Lección 3.4: CTE (Common Table Expressions)

Las CTE crean consultas temporales con nombre que puedes reutilizar, mejorando la legibilidad.

-- CTE para calcular ventas mensuales WITH VentasMensuales AS ( SELECT YEAR(FechaPedido) AS Año, MONTH(FechaPedido) AS Mes, SUM(Total) AS TotalVentas FROM Pedidos GROUP BY YEAR(FechaPedido), MONTH(FechaPedido) ) SELECT * FROM VentasMensuales WHERE TotalVentas > 5000;

Ejercicios de Práctica del Módulo 3

  1. Encuentra todos los productos cuyo precio es mayor que el precio promedio de su categoría.
  2. Muestra los clientes que han gastado más que el promedio de todos los clientes.
  3. Usa una CTE para calcular el ranking de vendedores por cantidad de ventas.
  4. Encuentra los productos que se han vendido más que cualquier producto de la categoría 'Electrónicos'.
  5. Crea una subconsulta para mostrar el cliente más reciente y sus detalles.

Módulo 4: Índices y Optimización de Rendimiento

Los índices son la clave para consultas rápidas en grandes volúmenes de datos. Aprende a crear y mantenerlos eficientemente.

Lección 4.1: Conceptos de índices (clustered vs non-clustered)

Los índices son como el índice de un libro. Clustered ordena físicamente los datos, solo puede haber uno por tabla. Non-clustered crea una estructura separada para búsquedas rápidas.

-- Ver índices existentes SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID('Clientes');

Lección 4.2: Creación y administración de índices

Crea índices en columnas frecuentemente buscadas o unidas.

-- Índice non-clustered en la columna Email CREATE INDEX IX_Clientes_Email ON Clientes(Email); -- Índice compuesto en varias columnas CREATE INDEX IX_Pedidos_ClienteFecha ON Pedidos(ClienteID, FechaPedido);

Lección 4.3: Análisis de planes de ejecución

Usa SET SHOWPLAN_ALL ON o el visualizador de SSMS para ver cómo SQL Server ejecuta tu consulta y encontrar cuellos de botella.

-- Ver plan de ejecución sin ejecutar SET SHOWPLAN_ALL ON GO SELECT * FROM Pedidos WHERE ClienteID = 123 GO SET SHOWPLAN_ALL OFF

Lección 4.4: Buenas prácticas de optimización

  • Indexa columnas en cláusulas WHERE, JOIN y ORDER BY
  • Evita funciones en columnas indexadas en WHERE
  • Usa SELECT específico en lugar de SELECT *
  • Mantén las estadísticas actualizadas

Ejercicios de Práctica del Módulo 4

  1. Crea un índice en la tabla Productos para optimizar búsquedas por nombre.
  2. Analiza el plan de ejecución de una consulta grande y sugiere mejoras.
  3. Crea un índice compuesto para optimizar la búsqueda de pedidos por cliente y fecha.
  4. Investiga qué índices son más utilizados en tu base de datos.
  5. Elimina índices redundantes que no se están usando.

Módulo 5: Procedimientos Almacenados y Funciones

Automatiza tareas complejas y encapsula lógica de negocio en objetos reutilizables y seguros.

Lección 5.1: Creación y ejecución de procedimientos

Los procedimientos almacenan consultas y lógica compleja que puedes ejecutar con un simple comando.

-- Crear procedimiento para obtener clientes activos CREATE PROCEDURE sp_ObtenerClientesActivos @FechaInicio DATE, @FechaFin DATE AS BEGIN SELECT * FROM Clientes WHERE FechaUltimaCompra BETWEEN @FechaInicio AND @FechaFin; END; -- Ejecutar el procedimiento EXEC sp_ObtenerClientesActivos '2024-01-01', '2024-12-31';

Lección 5.2: Parámetros de entrada y salida

Pasa valores a los procedimientos y recibe resultados calculados.

-- Procedimiento con parámetro de salida CREATE PROCEDURE sp_CalcularTotalVentas @ClienteID INT, @TotalVentas DECIMAL(10,2) OUTPUT AS BEGIN SELECT @TotalVentas = ISNULL(SUM(Total), 0) FROM Pedidos WHERE ClienteID = @ClienteID; END; -- Usar el procedimiento DECLARE @Total DECIMAL(10,2); EXEC sp_CalcularTotalVentas 123, @Total OUTPUT; SELECT @Total AS TotalVentasCliente;

Lección 5.3: Funciones definidas por el usuario

Las funciones devuelven un valor y pueden usarse en SELECT, WHERE, etc.

-- Función para calcular descuento CREATE FUNCTION fn_CalcularDescuento (@Precio DECIMAL(10,2), @Porcentaje INT) RETURNS DECIMAL(10,2) AS BEGIN RETURN @Precio * (1 - @Porcentaje / 100.0); END; -- Usar la función SELECT Producto, Precio, dbo.fn_CalcularDescuento(Precio, 15) AS PrecioConDescuento FROM Productos;

Lección 5.4: Manejo de errores y transacciones

Asegura la integridad de los datos con TRY-CATCH y transacciones.

-- Procedimiento con manejo de errores CREATE PROCEDURE sp_ProcesarPedido @ClienteID INT, @Total DECIMAL(10,2) AS BEGIN BEGIN TRY BEGIN TRANSACTION -- Validar cliente IF NOT EXISTS (SELECT 1 FROM Clientes WHERE ClienteID = @ClienteID) THROW 50001, 'Cliente no existe', 1; -- Insertar pedido INSERT INTO Pedidos(ClienteID, Total, Fecha) VALUES (@ClienteID, @Total, GETDATE()); COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION THROW END CATCH END

Ejercicios de Práctica del Módulo 5

  1. Crea un procedimiento que actualice el stock de productos después de una venta.
  2. Crea una función que valide si un email tiene formato correcto.
  3. Implementa un procedimiento que genere reportes mensuales de ventas.
  4. Crea una función que calcule la edad a partir de la fecha de nacimiento.
  5. Desarrolla un procedimiento con transacción para transferir fondos entre cuentas.