PostgreSQL中如何将指定列整体上移一行且不影响其他列
问题描述
现有名为lifelong的表,数据如下:
id first_meal last_meal 0 1 2022-07-25 12:28:00 2022-07-25 20:06:00 1 2 2022-07-26 13:12:00 2022-07-26 19:09:00 2 3 2022-07-27 14:13:00 2022-07-27 20:13:00 3 4 2022-07-28 15:10:00 2022-07-28 21:22:00
需要实现:将first_meal列整体上移一行(丢弃首行数据,后续行上移,末行置空),last_meal列保持原有数据不变,最终结果保存到新表,期望输出如下:
id first_meal last_meal 0 1 2022-07-26 13:12:00 2022-07-25 20:06:00 1 2 2022-07-27 14:13:00 2022-07-26 19:09:00 2 3 2022-07-28 15:10:00 2022-07-27 20:13:00 3 4 NaN 2022-07-28 21:22:00
尝试过以下SQL语句但未成功:
WITH cte AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY first_meal DESC) rn FROM lifelong ) INSERT INTO newTable (id, first_meal, last_meal) SELECT id, CASE WHEN rn > 1 THEN first_meal END, last_meal FROM cte;
可行解决方案
方案1:使用LEAD窗口函数(推荐,适用于支持窗口函数的数据库如PostgreSQL、MySQL 8+、SQL Server等)
-- 若新表未创建,先执行创建语句 CREATE TABLE newTable ( id INT, first_meal DATETIME, last_meal DATETIME ); -- 插入处理后的数据到新表 INSERT INTO newTable (id, first_meal, last_meal) SELECT id, LEAD(first_meal) OVER (ORDER BY id) AS first_meal, last_meal FROM lifelong;
- 原理:
LEAD(first_meal) OVER (ORDER BY id)会按id升序,获取当前行的下一行first_meal值,最后一行无后续行,返回NULL(对应期望的NaN)。 last_meal直接取原表值,保持不变。
方案2:自连接方式(适用于不支持窗口函数的旧版本数据库)
-- 若新表未创建,先执行创建语句 CREATE TABLE newTable ( id INT, first_meal DATETIME, last_meal DATETIME ); -- 插入处理后的数据到新表 INSERT INTO newTable (id, first_meal, last_meal) SELECT l1.id, l2.first_meal, l1.last_meal FROM lifelong l1 LEFT JOIN lifelong l2 ON l1.id + 1 = l2.id ORDER BY l1.id;
- 原理:通过自连接,将当前行
l1的id+1与另一行l2的id匹配,用l2的first_meal作为l1的新值,最后一行无匹配的l2,first_meal自动为NULL。
内容的提问来源于stack exchange,提问作者data_runner
相关产品推荐
相关产品推荐

