Con GROUP BY puedes saber cuánto ha gastado cada cliente, pero pierdes el detalle: cada grupo queda reducido a una fila. Las funciones de ventana hacen el mismo cálculo sin juntar las filas. Cada pedido sigue apareciendo, y a su lado puedes poner el total de su cliente, la media de su categoría o su posición en un ranking.

Una función se convierte en función de ventana cuando le añades OVER:

Sintaxis
funcion(columna) OVER (
    [PARTITION BY columnas]
    [ORDER BY columnas]
)
  • OVER () vacío: la ventana es todo el resultado.
  • PARTITION BY: divide las filas en grupos y calcula la función en cada uno por separado.
  • ORDER BY: establece un orden dentro de cada grupo. Lo necesitan las funciones de ranking, LAG y LEAD y los totales acumulados.

OVER (): un total al lado de cada fila

El total de ventas de la tienda junto a cada pedido, y el porcentaje que representa cada uno:

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
producto totalPrecio ventasTotales porcentaje
Xiami Mi 11 4304,25 17251,60 24,9
Echo DOT 4 2999,50 17251,60 17,4
MacBook Pro M1 2449,50 17251,60 14,2
Play Station 5 2199,80 17251,60 12,8
Echo DOT 3 1999,50 17251,60 11,6
Horno Balay 1399,10 17251,60 8,1
Xbox series X 999,98 17251,60 5,8
Nintendo Switch 899,97 17251,60 5,2

Con GROUP BY esto necesitaría una subconsulta para calcular el total y otra consulta para cruzarlo con cada fila.

PARTITION BY: el cálculo por grupos

Ahora el total y el número de pedidos de cada cliente, sin dejar de ver cada pedido:

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
nombre producto totalPrecio pedidosCliente gastoCliente
Alejandro Nintendo Switch 899,97 1 899,97
Ana Xiami Mi 11 4304,25 1 4304,25
Fernando MacBook Pro M1 2449,50 1 2449,50
Luis Echo DOT 4 2999,50 2 4999,00
Luis Echo DOT 3 1999,50 2 4999,00
María Play Station 5 2199,80 2 3199,78
María Xbox series X 999,98 2 3199,78

María y Luis tienen dos filas cada uno, y en las dos aparece su gasto total. Compáralo con el equivalente agrupado, que solo devuelve una fila por cliente:

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
nombre pedidosCliente gastoCliente
Alejandro 1 899,97
Ana 1 4304,25
Fernando 1 2449,50
Luis 2 4999,00
María 2 3199,78

Comparar cada fila con su grupo

Lo interesante de tener el valor del grupo al lado es poder operar con él. Por ejemplo, cuánto se aleja el precio de cada producto de la media de su descripción:

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
descripcionProducto producto precio precioMedio diferencia
Altavoz Alexa Echo DOT 3 39,99 49,99 -10,00
Altavoz Alexa Echo DOT 4 59,99 49,99 10,00
Consola Nintendo Nintendo Switch 299,99 299,99 0,00
Consola Sony Play Station 5 549,95 549,95 0,00
Consola Xbox Xbox series X 499,99 499,99 0,00

Los dos altavoces Alexa comparten descripción, así que su media es la de ambos (49,99 €) y cada uno queda 10 € por encima o por debajo. Cada consola tiene una descripción distinta, así que es su propio grupo y la diferencia es 0.

Qué funciones admiten OVER

Tipo Funciones
Agregadas SUM, COUNT, AVG, MIN, MAX
Ranking ROW_NUMBER, RANK, DENSE_RANK, NTILE
Desplazamiento LAG, LEAD, FIRST_VALUE, LAST_VALUE

Dónde se pueden usar

Las funciones de ventana se calculan después del WHERE, el GROUP BY y el HAVING, justo antes del ORDER BY. Por eso:

  • Se pueden usar en el SELECT y en el ORDER BY.
  • No se pueden usar en el WHERE. Para filtrar por su resultado, calcúlalas en una CTE y filtra fuera, como verás en la siguiente lección.

Practica

  1. Añade al primer ejemplo una columna con el pedido más caro de toda la tienda (MAX ... OVER ()).
  2. Calcula, para cada pedido, qué porcentaje supone sobre el gasto total de su cliente.
  3. ¿Qué pasa si en el segundo ejemplo quitas el INNER JOIN y usas solo Pedidos? ¿Cómo aparece el pedido sin cliente?