Oracle - 分区集的行聚合和空处理

Posted

技术标签:

【中文标题】Oracle - 分区集的行聚合和空处理【英文标题】:Oracle - Aggregation of rows and null handling for partitioned set 【发布时间】:2021-02-25 11:36:22 【问题描述】:

给定以下数据结构:

CREATE TABLE ETL_TEST 
(
    CASE_NO NUMBER(10,0), 
    LINE_NO NUMBER(10,0), 
    COLUMN_NAME VARCHAR2(18), 
    CHANGE_DATE DATE,
    NEW_ENTRY VARCHAR2(255), 
    OLD_ENTRY VARCHAR2(255),

    CONSTRAINT CASE_PK 
        PRIMARY KEY (CASE_NO, LINE_NO, COLUMN_NAME)
);

测试数据在这里http://sqlfiddle.com/#!4/2f718c/1

对于每组 CASE_NO 和 LINO_NO,如果 COLUMN_NAME = 'REASON_TEXT',则必须创建包含 CASE_NO、LINE_NO 和 REASON_TEXT 列的聚合行,其中 REASON_TEXT 包含 NEW_ENTRY 的数据。

如果 COLUMN_NAME = 'REASON_TEXT' 为 null 或没有 COLUMN_NAME = 'REASON_TEXT' 则必须选择前一个 LINO_NO 的数据,其中 COLUMN_NAME = 'REASON_TEXT' (如果存在这样的条目)。

这张图应该能说明问题

我想知道这是否可以使用纯 Oracle SQL 来实现。我会知道谁在 PL/SQL 中解决这个问题,但是使用纯 SQL?挑战在于没有固定数量的 COLUMN_NAME = 'REASON_TEXT',因为它可以是零个或多个。

【问题讨论】:

【参考方案1】:

您可以使用窗口函数来填充缺失的数据——在本例中为 last_value()ignore nulls 选项:

select case_no, line_no,
       max(case when column_name = 'REASON_TEXT' then new_entry end) as line_reason,
       last_value( max(case when column_name = 'REASON_TEXT' then new_entry end) ignore nulls
                 ) over
                 (partition by case_no order by line_no 
                 ) as imputed_reason_text
from etl_test
group by case_no, line_no
order by 1, 2;

Here 是一个 SQL Fiddle。

【讨论】:

以上是关于Oracle - 分区集的行聚合和空处理的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 10g 从两个不同的行和列聚合成一行

oracle--聚合函数和case when结合使用

第十章 SQL聚合函数 STDDEV, STDDEV_SAMP, STDDEV_POP

Spark 地图端聚合:仅每个分区?

第十二章 SQL聚合函数 VARIANCE, VAR_SAMP, VAR_POP

在 Oracle 中具有聚合的 NOT HAVING(逆 HAVING)子句