SQL如何调整数据集实现不同周期实体数据对齐到同一行
实体多周期数据单行对齐实现方案
你需要实现的是典型的长表转宽表需求,窗口函数无法折叠多行数据为单行,确实不适用,以下是可直接落地的方案:
- 条件聚合(优先推荐,全SQL引擎兼容,性能最优)
基于你已经写好的CASE逻辑,搭配分组聚合即可一次性完成对齐,不需要多表关联,仅需扫描一次原始表。核心逻辑是按实体分组后,仅匹配对应周期的数值传入聚合函数,同一实体同一周期仅存在一条数据时,MAX/MIN/SUM这类聚合函数不会改变原始数值。
示例代码:SELECT entity, MAX(CASE WHEN period = '2022-03-31' THEN metric_value END) AS curr_period, MAX(CASE WHEN period = '2021-09-30' THEN metric_value END) AS prev_period, MAX(CASE WHEN period = '2021-03-31' THEN metric_value END) AS prev2_period FROM raw_source_table GROUP BY entity; - 原生PIVOT语法(适合支持行转列专用语法的数据库)
如果你使用的是SQL Server、Oracle、Snowflake、BigQuery这类支持PIVOT语法的引擎,可以直接用专用行转列函数,写法更简洁,底层执行逻辑和条件聚合完全一致,性能没有差异。
以SQL Server写法为例:SELECT entity, [2022-03-31] AS curr_period, [2021-09-30] AS prev_period, [2021-03-31] AS prev2_period FROM raw_source_table PIVOT ( MAX(metric_value) FOR period IN ([2022-03-31], [2021-09-30], [2021-03-31]) ) AS pivot_result; - 多表左连接(不推荐,仅作逻辑参考)
可以将原始表按三个周期分别过滤为三个子查询,再按实体字段左连接拼接,逻辑直观但需要多次扫描原始表,数据量较大时性能远低于前两种方案。
示例代码:SELECT curr.entity, curr.metric_value AS curr_period, prev.metric_value AS prev_period, prev2.metric_value AS prev2_period FROM (SELECT entity, metric_value FROM raw_source_table WHERE period = '2022-03-31') curr LEFT JOIN (SELECT entity, metric_value FROM raw_source_table WHERE period = '2021-09-30') prev ON curr.entity = prev.entity LEFT JOIN (SELECT entity, metric_value FROM raw_source_table WHERE period = '2021-03-31') prev2 ON curr.entity = prev2.entity;
提示:如果某实体缺失某一周期的数据,上述方案都会在对应字段返回NULL,符合对齐逻辑;如果需要将缺失值替换为0,用
COALESCE(对应字段, 0)包裹即可。
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

