You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:45:34