Сначала попробуйте сами: на собеседовании подсказки не будет.
Период начинается там, где остаток стал ненулевым после нуля или это первая запись договора: lag(balance) по договору и условие balance > 0 AND coalesce(prev, 0) = 0.
Конец периода это первая нулевая запись после начала минус один день. Её ищет коррелированный подзапрос min(dt) по нулевым строкам того же договора с dt > start. Если такой записи нет, coalesce подставляет 2999-12-31. Вычитание целого из date в PostgreSQL сдвигает дату на дни.
WITH marked AS (SELECT id_dog, dt, balance, lag(balance) OVER (PARTITION BY id_dog ORDER BY dt) AS prev FROM rest_history), starts AS (SELECT id_dog, dt FROM marked WHERE balance > 0 AND coalesce(prev, 0) = 0) SELECT s.id_dog, s.dt AS start_dt, coalesce((SELECT min(z.dt) FROM rest_history z WHERE z.id_dog = s.id_dog AND z.balance = 0 AND z.dt > s.dt) - 1, DATE '2999-12-31') AS end_dt FROM starts s