只要后面没有非空值,就在组中查找空值的第一个实例 - 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
我试图找到某个字段为空的第一行,但需要注意的是后面不能有非空值。如果没有空值或空值之后出现非空值,那么我根本不想 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