我有一个带有x列的表,该列具有许多类似这样的rendom值:
7
null
null
4
null
null
null
4
我需要检查NULL
之前的数字是否与NULL
之后的数字相同,如果是,请将NULL
转换为该数字。如果不是,则NULL
保留。因此,结果将是另一列具有以下值的列:
7
null
null
4
4
4
4
4
有人可以帮助我吗?
答案 0 :(得分:0)
使用窗口函数:
WITH cte AS (
SELECT t.*, SUM(CASE WHEN val IS NULL THEN 0 ELSE 1 END) OVER(ORDER BY id) AS grp
FROM t
)
SELECT c1.id, c1.val,
CASE WHEN c2.val = MIN(c1.val) OVER(PARTITION BY c1.grp)
THEN c2.val
ELSE c1.val
END AS filled_val
FROM cte c1
LEFT JOIN cte c2
ON c1.grp = c2.grp-1
AND c2.val IS NOT NULL;
答案 1 :(得分:0)
此答案假设您有一个用于对值进行排序的唯一列,称为id
(没有这样的列,您的问题就无法解决)。
如果使用的RDBMS在窗口功能(例如Oracle)中支持选项IGNORE NULLS
,则可以按以下步骤进行操作:
SELECT id, CASE WHEN val IS NULL AND lg = ld THEN lg ELSE val END val
FROM (
SELECT
id,
val,
LAG(val IGNORE NULLS) OVER(ORDER BY id) lg,
LEAD(val IGNORE NULLS) OVER(ORDER BY id) ld
FROM t
) x
ID | VAL -: | ---: 1 | 7 2 | null 3 | null 4 | 4 5 | 4 6 | 4 7 | 4 8 | 4
在不支持窗口函数的RDBMS(例如MySQL <8.0)上,您可以采用效率不高但安全的选项,即使用JOIN
和相关子查询来查找值的前一个和下一个记录不为空:
SELECT t1.id, CASE WHEN t0.val = t2.val THEN t0.val ELSE t1.val END val
FROM t t1
LEFT JOIN t t0
ON t1.val IS NULL
AND t0.val IS NOT NULL
AND t0.id < t1.id
AND NOT EXISTS (SELECT 1 FROM t WHERE val IS NOT NULL AND id < t1.id AND id > t0.id)
LEFT JOIN t t2
ON t1.val IS NULL
AND t2.val IS NOT NULL
AND t2.id > t1.id
AND NOT EXISTS (SELECT 1 FROM t WHERE val IS NOT NULL AND id > t1.id AND id < t2.id)