Teradata SQL如何提取每个ID首次Complaint>0后的所有行
Teradata SQL 提取分组内首次满足条件记录及后续行
基础信息
当前使用Teradata SQL,待查询表包含ID、MonthID、Acc、Complaint四个字段,样例数据如下:
- ID=1:共3条记录,MonthID依次为202202、202203、202204,对应Acc值为5、4、3,Complaint值为1、2、0
- ID=2:共3条记录,MonthID依次为202202、202203、202204,对应Acc值为2、3、2,Complaint值为0、1、3
- ID=3:共3条记录,MonthID依次为202202、202203、202204,对应Acc值为1、2、3,Complaint值均为0
查询要求
按ID、MonthID排序,提取每个ID分组下,首次出现Complaint>0的记录及该记录之后的所有行,预期返回结果:
- ID=1的全部3条记录(首次Complaint>0出现在202202月)
- ID=2下MonthID为202203、202204的2条记录(首次Complaint>0出现在202203月)
- 不返回ID=3的任何记录(该ID下无Complaint>0的记录)
原有写法问题
之前尝试的SQL未达到预期,代码如下:
select a.*, row_number() over (partition by ID order by Complaint, MonthID) from table a
该写法排序逻辑错误:按Complaint排序会将所有Complaint>0的记录前置,既无法定位首次出现Complaint>0的时间点,也无法筛选该时间点之后的行。
正确实现方案
写法1:聚合子查询关联
通过子查询先计算每个ID首次出现Complaint>0的月份,再关联筛选符合时间条件的记录,兼容性最好:
SELECT t.* FROM your_table t INNER JOIN ( SELECT ID, MIN(CASE WHEN Complaint > 0 THEN MonthID END) AS first_complaint_month FROM your_table GROUP BY ID ) tmp ON t.ID = tmp.ID AND t.MonthID >= tmp.first_complaint_month ORDER BY t.ID, t.MonthID;
写法2:窗口函数直接计算
Teradata支持窗口函数内直接计算分组内首次满足条件的月份,写法更简洁,不需要关联:
SELECT ID, MonthID, Acc, Complaint FROM ( SELECT *, MIN(CASE WHEN Complaint > 0 THEN MonthID END) OVER (PARTITION BY ID) AS first_complaint_month FROM your_table ) t WHERE MonthID >= first_complaint_month ORDER BY ID, MonthID;
逻辑说明
- 用
CASE WHEN Complaint > 0 THEN MonthID END把不满足条件的记录置为NULL,MIN聚合/窗口计算时会自动忽略NULL值,得到每个ID下首次出现投诉的月份 - 无任何Complaint>0记录的ID,计算出的
first_complaint_month为NULL,关联/where筛选时会被自动过滤,符合需求 - 最终筛选
MonthID >= first_complaint_month的记录,刚好覆盖首次投诉当月及后续所有行
内容的提问来源于stack exchange,提问作者samronaldo309
相关产品推荐
相关产品推荐

