只要后面没有非空值,就在组中查找空值的第一个实例 - Teradata SQL

Find the first instance of a null value in a group as long as no non null comes after - Teradata SQL

我试图找到某个字段为空的第一行,但需要注意的是后面不能有非空值。如果没有空值或空值之后出现非空值,那么我根本不想 return 那个值。我正在使用 Teradata SQL,下面的模拟数据集应该可以说明我在寻找什么。

ID | Date      | Field_Of_Interest
A  | 1/1/2015  | 1
A  | 2/1/2015  | 1
A  | 3/1/2015  | 
A  | 4/1/2015  | 
A  | 5/1/2015  | 
B  | 1/1/2015  | 1
B  | 2/1/2015  | 1
B  | 3/1/2015  | 
B  | 4/1/2015  | 1
B  | 5/1/2015  | 
C  | 1/1/2015  | 1
C  | 2/1/2015  | 1
C  | 3/1/2015  | 1
C  | 4/1/2015  | 1
C  | 5/1/2015  | 1
D  | 1/1/2015  | 1
D  | 2/1/2015  | 1
D  | 3/1/2015  | 
D  | 4/1/2015  | 
D  | 5/1/2015  | 1

期望的结果:

ID | Date      
A  | 3/1/2015
B  | 5/1/2015

因为 C 和 D 的最后一条记录是非空的,所以我不想要它们。

我 运行 遇到麻烦的地方是像 B 或 D 这样的情况,在这些情况下我不能只取 Field_Of_Interest 为空的日期字段的最小值。我的另一个想法是找到 null 的最小值和不为 null 的最大值,如果 min 的日期大于 max 的日期,则使用它。问题出在 B 中,非空值出现在空值之后,然后返回到空值。

有什么想法吗?

您可以使用不同的行号或使用子查询来做到这一点。后一种方法会产生如下查询:

select id, min(date)
from t
where t.field_of_interest is null and
      not exists (select 1
                  from t
                  where t2.id = t.id and t2.date > t.date and
                        t2.field_of_interest is not null
                 )
group by id;

这是你想要的吗?

SELECT
    T1.ID,
    MIN(T1.some_date) AS some_date
FROM
    My_Table T1
WHERE
    T1.some_column IS NULL AND
    NOT EXISTS (SELECT * FROM My_Table T2 WHERE T2.ID = T1.ID AND T2.some_date > T1.some_date AND T2.some_column IS NOT NULL)
GROUP BY
    T1.ID

或者:

SELECT
    T1.id,
    MIN(T1.some_date) AS some_date
FROM
    My_Table T1
LEFT OUTER JOIN My_Table T2 ON
    T2.id = T1.id AND
    T2.some_date > T1.some_date AND
    T2.some_column IS NOT NULL
WHERE
    T1.some_column IS NULL AND
    T2.id IS NULL
GROUP BY
    T1.id

您可以使用窗口聚合函数通过单个 table 访问获得预期结果。根据实际 data/query 这可能更有效。

SELECT ID, MIN(dt)
FROM
 (
   SELECT *
   FROM tab
   QUALIFY
      -- returns NULL until the first row with a value in Field_Of_Interest
      MIN(Field_Of_Interest) 
      OVER (PARTITION BY ID
            ORDER BY dt DESC
            ROWS UNBOUNDED PRECEDING) IS NULL
 ) AS dt
GROUP BY 1