我有下表

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;

所有输出:

CP ROK DOPIS_C POSILANI
6059150790 2014 C 1
6059150790 2015 C 2
6059150790 2016 C 3
6059150790 2017 null null
6059150790 2018 C 1
6059150790 2019 null null
6059150790 2020 C 1
6059150790 2021 C 2
6059150790 2022 C 3
6059150790 2023 null null
6059150790 2024 null null

fiddle

Sql相关问答推荐

优化SQL查询流

如何解决Error:operator is not unique:unknown—unknown在一个动态SQL查询?""""

用于动态查询情况的存储过程常识模式

Postgres,使用iLike运算符从json数组中搜索的工作方式与从常规表中搜索不同

使用Mac日志(log)时间找出SQL中的好小时和坏小时

为表中每个缺少的引用创建新行

如何在presto/SQL中使用两个数组列创建(分解)单独的行

PostgreSQL抽奖查询

直接加法(1+1)与聚合函数SUM(1+1)的区别是什么

将Dense_RANK列为聚合(非解析)函数(&A)

在SQL Server中设置关联对象的有效JSON格式

如果另一个表中不存在值列,则插入失败

POSTGRES to_timestamp() 假定 UTC 字符串为本地时间

SQL Server中使用min()和max()从选定的特定值id表中删除不必要的时间

SQL Server:时态表并在运行时添加计算列

Postgres存在限制问题「小值」

如何使用SQL将患者平均分配给他们所在地区的doctor

SQL Select 最大并获取列名

如何从 2 个 SQLite 表构建嵌套对象?

PostgreSQL 如何在一组项目及其数量上找到完全相同的订单?