NTILE

NTILE divide las filas de cada partición en un número especificado de grupos aproximadamente iguales y asigna a cada fila el número de su grupo. Si tienes 100 empleados y usas NTILE(4), obtienes cuatro grupos de 25 empleados cada uno, numerados del 1 al 4. Es la función ideal para crear cuartiles, terciles, deciles o cualquier segmentación equitativa de datos.

A diferencia de RANK y DENSE_RANK, que clasifican según valores, NTILE clasifica según posición relativa. No le importa si el salario más alto es 200000 o 20000: simplemente divide las filas en N cubetas de tamaño similar según el orden que definas.

Sintaxis

NTILE(n) OVER (
    [PARTITION BY columna1, columna2, ...]
    ORDER BY columna1 [ASC|DESC], columna2 [ASC|DESC], ...
)

El argumento n es un entero positivo que indica cuántos grupos crear. Si n es mayor que el número de filas, algunas filas recibirán un grupo propio y los grupos restantes estarán vacíos (en la práctica, no se crean más grupos que filas). El ORDER BY determina cómo se ordenan las filas antes de repartirlas en grupos.

Comportamiento básico

Supón que tienes 8 empleados y quieres dividirlos en 4 grupos según su salario:

SELECT
    nombre,
    salario,
    NTILE(4) OVER (ORDER BY salario DESC) AS cuartil
FROM empleados;
nombresalariocuartil
Carlos López72000.001
Roberto Fernández65000.001
Ana García58000.002
Marta Ruiz55000.002
Laura Díaz52000.003
David Moreno48000.003
Elena Torres45000.004
Pedro Sánchez43000.004

Con 8 filas y 4 grupos, cada grupo recibe exactamente 2 filas. El cuartil 1 contiene los dos salarios más altos, y el cuartil 4 los dos más bajos. Este tipo de segmentación es fundamental en análisis estadísticos y de negocio.

Distribución desigual

Cuando el número de filas no es divisible exactamente entre n, los primeros grupos reciben una fila extra. Con 10 filas y 3 grupos, los tamaños serían 4, 3 y 3:

SELECT
    nombre,
    salario,
    NTILE(3) OVER (ORDER BY salario DESC) AS tercil
FROM empleados;
nombresalariotercil
Carlos López72000.001
Roberto Fernández68000.001
Ana García65000.001
Marta Ruiz62000.001
Laura Díaz58000.002
David Moreno55000.002
Elena Torres52000.002
Pedro Sánchez48000.003
Sofía Navarro45000.003
Javier Ruiz43000.003

El primer tercil tiene 4 filas mientras que los otros dos tienen 3. MySQL siempre asigna las filas sobrantes a los primeros grupos, de forma que la diferencia de tamaño entre el grupo más grande y el más pequeño es como máximo 1.

Caso práctico: bandas salariales automáticas

Recursos Humanos puede usar NTILE para crear bandas salariales equitativas de forma automática, sin definir rangos fijos:

SELECT
    NTILE(3) OVER (
        PARTITION BY departamento
        ORDER BY salario DESC
    ) AS banda,
    nombre,
    departamento,
    salario,
    CASE NTILE(3) OVER (PARTITION BY departamento ORDER BY salario DESC)
        WHEN 1 THEN 'Senior'
        WHEN 2 THEN 'Mid-level'
        WHEN 3 THEN 'Junior'
    END AS nivel
FROM empleados
ORDER BY departamento, banda;
bandanombredepartamentosalarionivel
1Roberto FernándezMarketing72000.00Senior
2Laura DíazMarketing58000.00Mid-level
3Sofía MorenoMarketing45000.00Junior
1Carlos LópezVentas68000.00Senior
1Ana GarcíaVentas65000.00Senior
2Marta RuizVentas55000.00Mid-level
3Pedro SánchezVentas48000.00Junior

Cada departamento se divide independientemente en 3 bandas. En Ventas, con 4 empleados divididos en 3 grupos, la primera banda recibe 2 personas (Carlos y Ana son "Senior") mientras que las otras bandas reciben 1 cada una.

Caso práctico: análisis por deciles de clientes

Los deciles son una herramienta clásica en análisis de negocio. Dividir clientes en 10 grupos según su gasto permite identificar qué segmento genera más ingresos:

WITH clientes_decil AS (
    SELECT
        c.nombre,
        SUM(p.total) AS gasto_total,
        NTILE(10) OVER (ORDER BY SUM(p.total) DESC) AS decil
    FROM clientes c
        JOIN pedidos p ON c.id_cliente = p.id_cliente
    GROUP BY c.id_cliente, c.nombre
)
SELECT
    decil,
    COUNT(*) AS num_clientes,
    ROUND(MIN(gasto_total), 2) AS gasto_min,
    ROUND(MAX(gasto_total), 2) AS gasto_max,
    ROUND(SUM(gasto_total), 2) AS gasto_grupo,
    ROUND(AVG(gasto_total), 2) AS gasto_medio
FROM clientes_decil
GROUP BY decil
ORDER BY decil;
decilnum_clientesgasto_mingasto_maxgasto_grupogasto_medio
1508200.0025400.00682000.0013640.00
2505100.008150.00328500.006570.00
3503400.005050.00210750.004215.00
4502200.003380.00138600.002772.00
5501500.002180.0091500.001830.00

Este análisis revela un patrón clásico: el decil 1 (el 10% de clientes con mayor gasto) genera más ingresos que los deciles 3, 4 y 5 juntos. Este es el famoso principio de Pareto aplicado al negocio, y NTILE lo hace visible sin esfuerzo.

Caso práctico: cuartiles para evaluación de rendimiento

Las evaluaciones de rendimiento a menudo clasifican a los empleados en cuartiles. El cuartil 1 son los de mejor rendimiento y el cuartil 4 los que necesitan mejora:

SELECT
    nombre,
    departamento,
    puntuacion_evaluacion,
    NTILE(4) OVER (ORDER BY puntuacion_evaluacion DESC) AS cuartil,
    CASE NTILE(4) OVER (ORDER BY puntuacion_evaluacion DESC)
        WHEN 1 THEN 'Excepcional'
        WHEN 2 THEN 'Supera expectativas'
        WHEN 3 THEN 'Cumple expectativas'
        WHEN 4 THEN 'Necesita mejora'
    END AS evaluacion
FROM empleados
WHERE activo = 1
ORDER BY cuartil, puntuacion_evaluacion DESC;
nombredepartamentopuntuacion_evaluacioncuartilevaluacion
Ana GarcíaVentas951Excepcional
Carlos LópezVentas921Excepcional
Roberto FernándezMarketing882Supera expectativas
Laura DíazMarketing852Supera expectativas
Marta RuizVentas783Cumple expectativas
David MorenoSoporte753Cumple expectativas
Elena TorresSoporte684Necesita mejora
Pedro SánchezVentas624Necesita mejora

El sistema de cuartiles es equitativo porque cada categoría tiene el mismo número de personas, a diferencia de una clasificación por rangos fijos donde podría haber categorías vacías o desequilibradas.

Manejo de NULL

Cuando la columna de orden contiene valores NULL, NTILE los trata como cualquier otro valor y los incluye en la distribución. En orden ascendente, los NULL aparecen primero y se asignan a los primeros grupos:

SELECT
    nombre,
    comision,
    NTILE(3) OVER (ORDER BY comision) AS grupo
FROM empleados;
nombrecomisiongrupo
Pedro SánchezNULL1
Elena TorresNULL1
David Moreno3000.001
Roberto Fernández5000.002
Marta Ruiz5000.002
Ana García8000.003
Carlos López12000.003

Los empleados sin comisión quedan en el grupo 1 junto con el de menor comisión. Si esto distorsiona tu análisis, filtra los NULL con WHERE comision IS NOT NULL antes de aplicar NTILE.

Combinación con otras funciones

NTILE se combina bien con funciones de agregación de ventana para enriquecer el análisis de segmentación:

WITH segmentos AS (
    SELECT
        nombre,
        salario,
        NTILE(4) OVER (ORDER BY salario DESC) AS cuartil,
        AVG(salario) OVER () AS promedio_global
    FROM empleados
)
SELECT
    cuartil,
    COUNT(*) AS empleados,
    ROUND(AVG(salario), 2) AS salario_medio_cuartil,
    ROUND(AVG(promedio_global), 2) AS salario_medio_global,
    ROUND(AVG(salario) / AVG(promedio_global) * 100, 1) AS indice
FROM segmentos
GROUP BY cuartil
ORDER BY cuartil;
cuartilempleadossalario_medio_cuartilsalario_medio_globalindice
1268500.0054750.00125.1
2256500.0054750.00103.2
3250000.0054750.0091.3
4244000.0054750.0080.4

El índice muestra que el cuartil 1 gana un 25% más que el promedio, mientras que el cuartil 4 gana un 20% menos. Este tipo de análisis es habitual en estudios de equidad salarial.

Practica con NTILE

Usa el editor para dividir resultados en grupos iguales:

Simulador SQL
Ctrl+Enter para ejecutar

En el siguiente artículo veremos LAG para acceder a filas anteriores.

Escrito por Eduardo Lázaro