Cómo utilizar la función LAST() y FIRST() en MySQL

Lo primero que hay que decir es que LAST() y FIRST() no existen en MySQL. Son funciones de agregación de Microsoft Access, no del SQL estándar; lo que el estándar define son FIRST_VALUE() y LAST_VALUE(), que son funciones de ventana. Pero se puede conseguir el mismo efecto con una pequeña trampa:

SELECT
  agrupacion,
  MIN(valor) AS minimo,
  MAX(valor) AS maximo,
  AVG(valor) AS media,
  SUBSTRING_INDEX(GROUP_CONCAT(valor ORDER BY fecha), ',', 1)      AS primer_valor,
  SUBSTRING_INDEX(GROUP_CONCAT(valor ORDER BY fecha DESC), ',', 1) AS ultimo_valor
FROM datos
GROUP BY agrupacion;

GROUP_CONCAT junta todos los valores del grupo en una cadena, en el orden que le digas, y SUBSTRING_INDEX se queda con lo que hay antes de la primera coma: el primero de la lista. Ordenando al revés, el último.

Es útil cuando queremos sacar los distintos valores de una tabla de históricos, por ejemplo, como esta:

idproducto_idpreciofecha
12350.002014-02-15
22353.002014-02-18
32360.002014-02-20
42348.002014-02-23
52343.002014-02-25
62351.002014-02-28

En esta tabla, valor sería el campo precio y agrupacion sería producto_id. Para el producto 23 saldría mínimo 43, máximo 60, primer precio 50 y último 51, todo en una sola consulta.

Lo que hay que saber antes de usarlo

  • La cadena tiene un límite. GROUP_CONCAT corta el resultado en group_concat_max_len bytes, y lo hace sin avisar. Con el primer valor no pasa nada, porque va al principio, pero si el grupo es enorme conviene subirlo: SET SESSION group_concat_max_len = 1000000;
  • Devuelve texto, no número. Si vas a operar con él, conviértelo: CAST(... AS DECIMAL(10,2)).
  • Si el valor lleva comas, el corte falla. Usa otro separador: GROUP_CONCAT(valor ORDER BY fecha SEPARATOR '|') y corta por '|'.
  • Si dos filas tienen la misma fecha, añade el id al ORDER BY para que el resultado no dependa del azar.

Hoy hay formas mejores

Esto lo escribí en 2014. Con MySQL 8 o MariaDB 10.2 en adelante ya hay funciones de ventana (FIRST_VALUE, LAST_VALUE, ROW_NUMBER) que lo resuelven sin trucos. Las cuento, junto con los índices para que vaya rápido, en Primer y último registro en MySQL: alternativas a FIRST() y LAST().

0 comentarios sobre "Cómo utilizar la función LAST() y FIRST() en MySQL"

Sé el primero en comentar.