Отказ от ответственности : Я не совсем понял ваш вариант использования с кварталами и то, как диапазоны start_flag
должны работать с течением времени.Таким образом, следующее решение не смотрит на временную часть.Если бы вы немного объяснили свой пример времени, я уверен, что следующему решению нужна лишь небольшая настройка (например, предложение PARTITION
) для получения работы за вас.
demo:db <> fiddle
Мои образцы данных:
id start_flag end_flag
1 0 0
2 1 0
3 0 0
4 0 0
5 0 1
6 0 0
7 1 0
8 0 1
9 0 0
10 0 1
11 0 0
12 0 1
13 1 0
14 0 0
16 0 0
Запрос:
SELECT
*,
GREATEST(
first_value(start_flag - end_flag) OVER (PARTITION BY sum ORDER BY id),
0
) as status
FROM (
SELECT
*,
SUM(start_flag + end_flag) OVER (ORDER BY id)
FROM mytable
) s
Результат:
id start_flag end_flag status
1 0 0 0
2 1 0 1
3 0 0 1
4 0 0 1
5 0 1 0
6 0 0 0
7 1 0 1
8 0 1 0
9 0 0 0
10 0 1 0
11 0 0 0
12 0 1 0
13 1 0 1
14 0 0 1
16 0 0 1
Объяснение:
Использование оконных функций :
- Совокупный
SUM
каждого потенциального "изменения состояния" (start_flag
или end_flag
).Это создает группы.В каждой группе одинаковый статус.(см. столбец SUM
в скрипте) first_value
оконная функция: для каждой группы проверять, было ли изменение статуса выполнено с помощью start_flag
(положительно) или end_flag
(отрицательно) GREATEST()
нормализует отрицательные значения до нуля.
Редактировать: Добавление prod_id
и year/quarters
В целом весь сценарий использования очень похож- только с использованием оконных функций:
демо: db <> fiddle
- Вместо того, чтобы заказывать по
id
, я заказываю по year, quarter
- Вместо просмотра всего набора данных я использую разделение (над
prod_id
) для оконных функций:
Расширенный запрос:
SELECT
*,
GREATEST(
first_value(start_flag - end_flag) OVER (PARTITION BY prod_id, sum ORDER BY year, quarter),
0
) as status
FROM (
SELECT
*,
SUM(start_flag + end_flag) OVER (PARTITION BY prod_id ORDER BY year, quarter)
FROM mytable
) s