窗口函数
与其调用COALESCE
,您可以直接从窗口函数lag()
提供默认值。在此情况下,这是一个细节问题,因为所有列都定义为NOT NULL
。但这可能对区分“没有前一行”和“前一行中的NULL”至关重要。
SELECT id, val
FROM (
SELECT id, val, <b>lag(val, 1, val)</b> OVER (ORDER BY id) <b><> val AS changed</b>
FROM p
) sub
WHERE changed
ORDER BY id;
立即计算比较结果,因为之前的值本身并不重要,只是可能发生了变化。更短,可能会稍微快一点。
如果您认为第一行已经“更改”(不像您的演示输出所示),那么您需要观察NULL
值 - 即使您的列被定义为NOT NULL
。基本的 lag()
在没有前一行的情况下返回NULL
:
SELECT id, val
FROM (
SELECT id, val, lag(val) OVER (ORDER BY id) IS DISTINCT FROM val AS changed
FROM p
) sub
WHERE changed
ORDER BY id;
或者再次使用lag()
的附加参数:
SELECT id, val
FROM (
SELECT id, val, <b>lag(val, 1, NOT val)</b> OVER (ORDER BY id) <b><> val AS changed</b>
FROM p
) sub
WHERE changed
ORDER BY id;
递归公共表达式 (Recursive CTE)
这只是一个概念证明。 :)
性能无法与已发布的替代方案相比。
WITH RECURSIVE cte AS (
SELECT id, val
FROM p
WHERE NOT EXISTS (
SELECT 1
FROM p p0
WHERE p0.id < p.id
)
UNION ALL
SELECT p.id, p.val
FROM cte
JOIN p ON p.id > cte.id
AND p.val <> cte.val
WHERE NOT EXISTS (
SELECT 1
FROM p p0
WHERE p0.id > cte.id
AND p0.val <> cte.val
AND p0.id < p.id
)
)
SELECT * FROM cte;
在@wildplasser的帮助下有所改进。
SQL Fiddle演示所有内容。