LAG

LAG(expr, N, default) OVER ([PARTITION BY …] ORDER BY …)

Renvoie la valeur de l’expression de la ligne située N lignes plus haut (par défaut 1) selon l’ordre de OVER. Pour la première ligne, renvoie la valeur par défaut, et sans elle NULL.

Paramètres

  • expr – la valeur lue dans la ligne précédente.
  • N – facultatif, de combien de lignes remonter. Par défaut 1.
  • default – facultatif, la valeur quand il n’y a pas de ligne précédente. MySQL la prend en charge, MariaDB (vérifié en versions 10.4 et 10.11) la refuse avec une erreur de syntaxe – de façon portable IFNULL(LAG(…) OVER (…), default).

Exemples

Les exemples avec les tables customers, products et orders utilisent la base de données d’exemple de la série Bases du SQL.

Combien de jours se sont écoulés depuis la commande précédente du même client :

SELECT customer_id, order_date,
  LAG(order_date) OVER (PARTITION BY customer_id ORDER BY order_date, id) AS previous,
  DATEDIFF(order_date, LAG(order_date) OVER (PARTITION BY customer_id ORDER BY order_date, id)) AS days
FROM orders
WHERE customer_id IN (1, 2)
ORDER BY customer_id, order_date, id;
+-------------+------------+------------+------+
| customer_id | order_date | previous   | days |
+-------------+------------+------------+------+
|           1 | 2026-01-05 | NULL       | NULL |
|           1 | 2026-01-05 | 2026-01-05 |    0 |
|           1 | 2026-02-20 | 2026-01-05 |   46 |
|           2 | 2026-01-12 | NULL       | NULL |
|           2 | 2026-03-15 | 2026-01-12 |   62 |
+-------------+------------+------------+------+

Le chiffre d’affaires par mois et l’évolution par rapport au mois précédent :

SELECT month_key, revenue, revenue - IFNULL(LAG(revenue) OVER (ORDER BY month_key), 0) AS difference
FROM (
  SELECT EXTRACT(YEAR_MONTH FROM o.order_date) AS month_key, SUM(o.quantity * p.price) AS revenue
  FROM orders o JOIN products p ON p.id = o.product_id
  GROUP BY month_key
) x
ORDER BY month_key;
+-----------+---------+------------+
| month_key | revenue | difference |
+-----------+---------+------------+
|    202601 |  110.80 |     110.80 |
|    202602 |   19.60 |     -91.20 |
|    202603 |   71.60 |      52.00 |
+-----------+---------+------------+

Points d’attention

  • Sans valeur par défaut, le résultat de la première ligne vaut NULL, et avec lui la différence – c’est pourquoi l’exemple utilise IFNULL().
  • L’ordre dans OVER (ORDER BY) n’est pas l’ordre du résultat – réglez les deux pour que le résultat ait un sens.
  • Les fonctions de fenêtrage existent dans MySQL depuis la version 8.0 et dans MariaDB depuis la 10.2. L’ancien MySQL 5.7 ne les a pas.

Voir aussi :
LEAD()
OVER
DATEDIFF()