Текущий итог каждого приращения

#mysql #sql #gaps-and-islands #mariadb-10.2

#mysql #sql #пробелы и острова #mariadb-10.2

Вопрос:

У меня есть таблица events следующего вида:

 f_id   leg   
1       1
2       1
3       1
4       2
5       2
6       3
7       1
8       1
9       2
  

Мне нужен текущий итог каждого leg изменения. Ожидаемый результат:

 f_id   leg     total_legs   
1       1         1
2       1         1
3       1         1
4       2         2
5       2         2
6       3         3
7       1         4
8       1         4
9       2         5
  

Не уверен, как это сделать.

 SELECT *, @leg_var:=IF(@current_leg=leg, leg) as total_legs FROM `events`
  

Это явно неправильно.

Комментарии:

1. Какую версию MySQL вы используете?

2. Использование MariaDB 10.2

Ответ №1:

 WITH cte AS ( SELECT *, CASE WHEN LAG(leg) OVER (ORDER BY f_id) = leg 
                             THEN 0 
                             ELSE 1 
                             END lag_leg
              FROM test )
SELECT f_id, leg, SUM(lag_leg) OVER (ORDER BY f_id) total_legs
FROM cte;
  

скрипка

Ответ №2:

Это своего рода проблема пробелов и островов. В MySQL 8.0 вы можете использовать lag() и накопительный sum() :

 select fid, leg, sum(not leg <=> lag_leg) over(order by f_id) total_legs
from (
    select e.*, lag(leg) over(order by f_id) lag_leg
    from events e
) e
  

Ответ №3:

Проблема может быть решена без оконных функций с использованием переменных:

 SET @leg_var:=null;
SET @total:=0;
SELECT 
    f_id, 
    @leg_var prev_leg, 
    @total:=@total if(@leg_var is null or @leg_var<>leg, 1, 0) as total,
    @leg_var:=leg as leg
FROM events
ORDER BY f_id;
  

скрипка здесь