Нужна помощь в использовании локальных переменных для вычитания предыдущего значения строки, имеющего несколько групп

У меня есть 3 таблицы следующим образом:

+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | int(11)      | NO   | PRI | 0       |       |
| full_name | varchar(200) | YES  |     | NULL    |       |
| gender    | varchar(1)   | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| actor_id | int(11) | YES  | MUL | NULL    |       |
| movie_id | int(11) | YES  | MUL | NULL    |       |
| salary   | int(11) | YES  |     | NULL    |       |
+----------+---------+------+-----+---------+-------+
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int(11)      | NO   | PRI | 0       |       |
| title | varchar(100) | YES  |     | NULL    |       |
| year  | int(11)      | YES  |     | NULL    |       |
| genre | varchar(100) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+

Я пытаюсь выяснить, у какого актера больше всего времени между фильмами.

Я пытаюсь использовать локальные переменные для ссылки на предыдущее значение строки в случае, когда актер был таким же (или по умолчанию он равен 0). Однако по какой-то причине переменная @previousName возвращает случайный список имен.

Вот код:

SELECT 
    a.full_name, 
    m.year,
    m.title,
    @PreviousName,
    @PreviousYear,
    if(@PreviousName = a.full_name, m.year - @PreviousYear, 0) AS Delta,
    @PreviousName := a.full_name,
    @PreviousYear := m.year 
FROM
    actors AS a
        INNER JOIN
    cast AS c ON a.id = c.actor_id
        INNER JOIN
    movies AS m ON c.movie_id = m.id,
    (SELECT @PreviousName := null, @PreviousYear := 999) as SQLVars
ORDER BY full_name;

И вот что я получаю: Изображение таблицы результатов

Обратите внимание, я использую MySQL V5.7, поэтому оконные функции не вариант.

1 ответ

Вы можете сделать это с помощью коррелированного подзапроса:

select mc.*, (year - prev_year) as diff
from (select c.*, m.year,
             (select m2.year
              from movies m2 join
                   cast c2
                   on c2.movie_id = m2.id
              where c2.actor_id = c.actor_id and
                    m2.year < m.year
              order by m2.year desc
              limit 1
             ) prev_year
      from movies m join
           cast c
           on c.movie_id = m.id
     ) mc
order by diff desc;

Это предполагает, что актер снимается не в двух фильмах одного года. Если бы у вас была дата релиза или что-то еще, это было бы более эффективно для заказа времени.

Другие вопросы по тегам