У меня есть следующая таблица
CP ROK DOPIS_C
-----------------------
6059150790 2014 C
6059150790 2015 C
6059150790 2016 C
6059150790 2017
6059150790 2018 C
6059150790 2019
6059150790 2020 C
6059150790 2021 C
6059150790 2022 C
6059150790 2023
6059150790 2024
мне нужен этот вывод
CP ROK DOPIS_C RN_C1
---------------------------------
6059150790 2014 C 1
6059150790 2015 C 2
6059150790 2016 C 3
6059150790 2017
6059150790 2018 C 1
6059150790 2019
6059150790 2020 C 1
6059150790 2021 C 2
6059150790 2022 C 3
6059150790 2023
6059150790 2024
в столбце RN_C1 подсчитывается количество предыдущих записей, где DOPIS_C имеет значение C и если в предыдущей записи в столбце DOPIS_C имеется нулевое значение, счетчик сбрасывается
я пробую это
SELECT
CP,
ROK,
DOPIS_C,
CASE
WHEN DOPIS_C = 'C' THEN
CASE
WHEN lag(DOPIS_C) OVER (ORDER BY ROK) IS NULL THEN
ROW_NUMBER() OVER (ORDER BY ROK)
WHEN lag(DOPIS_C) OVER (ORDER BY ROK) = 'C' THEN
COUNT(CASE WHEN DOPIS_C = 'C' THEN 1 END) OVER (ORDER BY ROK)
END
ELSE 0
END AS POSILANI
FROM
table;
но результат
6059150790 2014 C 1
6059150790 2015 C 2
6059150790 2016 C 3
6059150790 2017 0
6059150790 2018 C 5
6059150790 2019 0
6059150790 2020 C 7
6059150790 2021 C 6
6059150790 2022 C 7
6059150790 2023 0
6059150790 2024 0
В Oracle 12 вы можете использовать MATCH_RECOGNIZE
для сопоставления шаблонов построчно:
SELECT cp,
rok,
dopis_c,
CASE dopis_c WHEN 'C' THEN posilani END AS posilani
FROM table_name
MATCH_RECOGNIZE(
PARTITION BY cp
ORDER BY rok
MEASURES
COUNT(dopis_c) AS posilani
ALL ROWS PER MATCH
PATTERN ( C+ | NOT_C )
DEFINE C AS dopis_c = 'C'
);
Или в более ранних версиях вы можете использовать несколько аналитических функций:
SELECT cp,
rok,
dopis_c,
rn,
CASE dopis_c
WHEN 'C'
THEN rn - COALESCE(
LAST_VALUE(CASE WHEN dopis_c IS NULL THEN rn END) IGNORE NULLS
OVER (PARTITION BY cp ORDER BY rok),
0
)
END AS posilani
FROM (
SELECT cp,
rok,
dopis_c,
ROW_NUMBER() OVER (PARTITION BY cp ORDER BY rok) AS rn
FROM table_name
);
или:
SELECT cp,
rok,
dopis_c,
CASE dopis_c
WHEN 'C'
THEN ROW_NUMBER() OVER (PARTITION BY cp, dopis_c, c_grp ORDER BY rok)
END AS posilani
FROM (
SELECT cp,
rok,
dopis_c,
COUNT(1) OVER (PARTITION BY cp ORDER BY rok)
- COUNT(dopis_c) OVER (PARTITION BY cp ORDER BY rok) AS c_grp
FROM table_name
)
ORDER BY
cp,
rok
Что для примера данных:
CREATE TABLE table_name (CP, ROK, DOPIS_C) AS
SELECT 6059150790, 2014, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2015, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2016, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2017, NULL FROM DUAL UNION ALL
SELECT 6059150790, 2018, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2019, NULL FROM DUAL UNION ALL
SELECT 6059150790, 2020, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2021, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2022, 'C' FROM DUAL UNION ALL
SELECT 6059150790, 2023, NULL FROM DUAL UNION ALL
SELECT 6059150790, 2024, NULL FROM DUAL;
Все выходы:
@feoftheda В общем, если у вас есть следующий вопрос, вам следует задать новый вопрос . В этом случае вы можете запустить MATCH_RECOGNIZE
дважды или использовать аналитические функции — несколько примеров находятся в этой скрипте.
Вы также можете сделать это без MATCH_RECOGNIZE, но с помощью подзапроса:
select cp, rok_dopis, c,
nvl2(c,row_number() over(partition by cp, c || n order by rok_dopis),null) as rn_c1
from (
select d.*,
sum(case when c is null then 1 else 0 end) over(partition by cp order by rok_dopis) as n
from table_name d
)
order by rok_dopis
;
Спасибо, а если бы я захотел включить в расчет еще один столбец, где принцип расчета был бы тот же. например столбец dopis_k, где будет получено количество вхождений «K»