Aprenda sobre las Funciones Window en PostgreSQL usando ChatGPT

Aprenda sobre las Funciones Window en PostgreSQL usando ChatGPT

Hace un par de semanas un cliente me solicitó que revisara con su equipo de desarrollo de software el uso de las funciones ventana (window) para posibilitar el diseño de consultas más claras y eficientes para el proyecto de un sistema web que estaban desarrollando.

Yo mismo, que dedico una gran parte de mi tiempo al análisis de datos y a administrar servidores de PostgreSQL, no las uso con frecuencia, así que acepté el reto y revisé el tema para poder atender la solicitud de consultoría.

¿Qué son las window functions? Para definir qué son y para que se usan las funciones ventana le pedí apoyo a ChatGPT, en su versión libre, por medio de la siguiente petición (prompt):

Prompt

Usando tu rol de experto en SQL escribe una definición detallada de las funciones window, que casos de uso tienen y sus ventajas.

Respuesta

Las funciones Window, también conocidas como funciones de ventana, son un conjunto de funciones en SQL que permiten realizar cálculos y análisis avanzados sobre un conjunto de filas, sin tener que recurrir a subconsultas o consultas anidadas.

Estas funciones operan en un "marco" o "ventana" de filas definido por una cláusula OVER. La cláusula OVER se utiliza para especificar cómo se deben agrupar y ordenar las filas en la ventana. Puede incluir expresiones PARTITION BY para dividir los datos en grupos más pequeños y ORDER BY para determinar el orden de las filas dentro de cada grupo.

A continuación, se presentan las principales características y ventajas de las funciones Window:

  • Cálculos avanzados: Las funciones Window permiten realizar cálculos avanzados sin necesidad de recurrir a consultas anidadas o subconsultas. Puedes realizar operaciones como suma acumulativa, promedios móviles, ranking, diferencias entre filas consecutivas, entre otros.

  • Agregación parcial: Las funciones Window se aplican a un conjunto de filas en lugar de a la tabla completa. Esto significa que puedes realizar cálculos agregados parciales dentro de cada ventana definida, lo que resulta útil cuando deseas obtener resultados parciales o realizar cálculos dentro de grupos específicos.

  • Flexibilidad en el marco de filas: La cláusula OVER permite definir el marco de filas sobre el cual se aplicarán las funciones Window. Puedes especificar rangos, intervalos, filas anteriores o siguientes, y más. Esto brinda una gran flexibilidad para adaptar los cálculos según tus necesidades específicas.

  • Eficiencia: Las funciones Window suelen ser más eficientes que las consultas anidadas o subconsultas para realizar cálculos avanzados. Al evitar la necesidad de múltiples consultas o procesamiento iterativo, las funciones Window pueden mejorar el rendimiento y reducir la complejidad de las consultas.

  • Mejora de la legibilidad del código: El uso de funciones Window puede hacer que las consultas sean más legibles y concisas. En lugar de escribir consultas complejas con subconsultas o uniones múltiples, las funciones Window te permiten expresar los cálculos y análisis de forma más clara y estructurada.

Los casos de uso comunes de las funciones Window incluyen:

  • Cálculo de totales acumulados, como sumas y promedios acumulativos.

  • Obtención de rankings o clasificaciones basados en ciertos criterios.

  • Cálculo de diferencias o variaciones entre filas consecutivas.

  • Realización de cálculos dentro de grupos o particiones específicas.

  • Generación de promedios móviles o suavizados de datos temporales.

  • Cálculo de porcentajes o proporciones en relación con el total.

En resumen, las funciones Window en SQL brindan una potente funcionalidad para realizar cálculos avanzados y análisis sobre conjuntos de filas de manera eficiente y legible. Su flexibilidad y versatilidad las convierten en una herramienta valiosa para abordar una amplia gama de escenarios y necesidades de consultas en bases de datos relacionales.

Vayamos a la práctica

Una vez que quedó clara la utilidad de las funciones ventana, viene la parte más interesante y útil: practicar lo aprendido para asegurarse que el conocimiento llegue a los cerebros correspondientes.

Prompt

Toma el rol de un experto en SQL en PostgreSQL. Vas a explicar el uso de funciones Window a programadores. Debes generar las tablas necesarias para los ejemplos que vas a dar, así como los datasets que van a poblar esas tablas. Debes generar ejemplos para diversos tipos de consultas usando funciones window, con selects a las tablas que definiste arriba.

Respuesta

Las tablas y los datasets que me recomendó ChatGPT en su respuesta fueron las siguientes:

CREATE TABLE ventas ( 
    id_venta SERIAL PRIMARY KEY, 
    fecha DATE, 
    producto VARCHAR(50), 
    cantidad INTEGER, 
    total DECIMAL(10, 2) 
);

Ahora, vamos a poblar la tabla ventas con algunos datos de ejemplo:

INSERT INTO ventas (fecha, producto, cantidad, total) VALUES 
('2023-01-01', 'Producto A', 5, 100.00), 
('2023-01-02', 'Producto B', 3, 75.00), 
('2023-01-03', 'Producto A', 2, 50.00), 
('2023-01-04', 'Producto C', 1, 25.00), 
('2023-01-05', 'Producto B', 4, 100.00), 
('2023-01-06', 'Producto A', 3, 75.00), 
('2023-01-07', 'Producto C', 2, 50.00), 
('2023-01-08', 'Producto B', 2, 50.00);

Con esta tabla y los datos de ejemplo, ahora podemos comenzar a estudiar las funciones window.

Primero vamos a ver la salida de una consulta común que usa ORDER BY:

SELECT fecha, sum(total) AS suma_acumulada FROM ventas GROUP BY 
fecha ORDER BY fecha;
fecha | suma_acumulada 
------------+---------------- 
2023-01-01 | 100.00 
2023-01-02 |  75.00 
2023-01-03 |  50.00 
2023-01-04 |  25.00 
2023-01-05 | 100.00 
2023-01-06 |  75.00 
2023-01-07 |  50.00 
2023-01-08 |  50.00

Ahora, algo mejor usando una función ventana:

SELECT fecha, total, SUM(total) OVER (ORDER BY fecha) AS 
suma_acumulada FROM ventas; 
    fecha  | total  | suma_acumulada 
-----------+--------+---------------- 
2023-01-01 | 100.00 | 100.00 
2023-01-02 |  75.00 | 175.00 
2023-01-03 |  50.00 | 225.00 
2023-01-04 |  25.00 | 250.00 
2023-01-05 | 100.00 | 350.00 
2023-01-06 |  75.00 | 425.00 
2023-01-07 |  50.00 | 475.00 
2023-01-08 |  50.00 | 525.00

La ventaja de usar una función ventana es que obtenemos algo más que la simple lista de las sumas acumuladas: al operar sobre la fecha conseguimos que la acumulación se de además sobre (OVER) las diversas fechas. Asegúrese por usted mismo que cada suma acumulada reponde a lo esperado.

Ahora veremos algunas aplicaciones de las funciones window con la tabla generada.

  1. Calcular el promedio móvil de ventas de los últimos 3 días

Aquí, utilizaremos la función AVG (promedio) con la cláusula OVER y la especificación ROWS BETWEEN 2 PRECEDING AND CURRENT ROW para calcular el promedio móvil de las ventas de los últimos 3 días, ordenados por fecha.

SELECT fecha, total, AVG(total) OVER (ORDER BY fecha ROWS 
BETWEEN 2 PRECEDING AND CURRENT ROW)::numeric(5,2) AS promedio_movil 
FROM ventas; 
      fecha | total | promedio_movil
------------+--------+----------------
 2023-01-01 | 100.00 | 100.00
 2023-01-02 |  75.00 | 87.50
 2023-01-03 |  50.00 | 75.00
 2023-01-04 |  25.00 | 50.00
 2023-01-05 | 100.00 | 58.33
 2023-01-06 |  75.00 | 66.67
 2023-01-07 |  50.00 | 75.00
 2023-01-08 |  50.00 | 58.33

Observe que la columna promedio_movil está calculando el promedio de dos renglones, el actual y el que se encuentra dos lugares arriba. Lograr una salida de este tipo usando subselects es más complejo y la consulta no es tan clara.

  1. Obtener el ranking de productos por monto total de venta

Para obtener una clasificación de los productos en función de su venta podemos usar una función hecha expresamente para ello, la función RANK. En esta consulta, usamos la función RANK con la cláusula OVER para asignar un ranking a cada producto según el monto total de venta, ordenado de forma descendente.

SELECT producto, total, RANK() OVER (ORDER BY total DESC) AS ranking 
FROM ventas;
   producto |  total | ranking
------------+--------+---------
 Producto A | 100.00 | 1 
 Producto B | 100.00 | 1
 Producto A |  75.00 | 3
 Producto B |  75.00 | 3
 Producto A |  50.00 | 5
 Producto B |  50.00 | 5
 Producto C |  50.00 | 5
 Producto C |  25.00 | 8

Conclusión

Estos son solamente algunos ejemplos sencillos de lo que se puede lograr usando las funciones ventana.

Diseñe algunas peticiones (prompts) a ChatGPT para contar con un par de tablas y las sentencias para poblarlas y solicite algunos ejemplos de funciones window usándolas.

Si tiene dudas o sugerencias sobre los temas que desea conocer escríbame a Roberto Andrade Fonseca.

Referencias

Para revisar las funciones ventana que proporciona PostgreSQL 15 visite la documentación oficial de PostgreSQL sobre el tema.