我有一张这样的表:
+------+-------+
|ID | value |
+------+-------+
| 1 | 150 |
| 2 | |
| 3 | |
| 4 | |
| 5 | 530 |
| 6 | 950 |
| 7 | 651 |
+-------+------+
我想复制最后3个值,最后我的表格如下:
+------+-------+
|ID | value |
+------+-------+
| 1 | 150 |
| 2 | 530 |
| 3 | 950 |
| 4 | 651 |
| 5 | 530 |
| 6 | 950 |
| 7 | 651 |
+-------+------+
有可能吗?
答案 0 :(得分:7)
使用自我加入:
UPDATE mytable m
SET value = m0.value
FROM mytable m0
WHERE m.id = (m0.id - 3) -- define offset
AND m.id BETWEEN 2 AND 4 -- define range to be affected
AND m.value IS NULL; -- make sure only NULL values are updated
如果ID空间中存在间隙,请使用windows函数row_number()
获取无间隙ID。我在CTE中这样做,因为我将重复使用表两次进行自我加入:
WITH x AS (
SELECT *, row_number() OVER (ORDER BY ID) AS rn
FROM mytable
)
UPDATE mytable m
SET value = y.value
FROM x
JOIN x AS y ON x.rn = (y.rn - 4567) -- JOIN CTE x AS y with an offset
WHERE x.id = m.id -- JOIN CTE x to original
AND m.id BETWEEN 1235 AND 3455
AND m.value IS NULL;
data-modifying CTEs需要PostgreSQL 9.1或更高版本。
答案 1 :(得分:0)
对于像这样的临时更新,可能不会有比三个简单更新语句更好的方法:
UPDATE mytable SET value = 530 WHERE id = 2;
UPDATE mytable SET value = 950 WHERE id = 3;
UPDATE mytable SET value = 651 WHERE id = 4;
问题是,这是一个临时更新,仅适用于此确切数据,还是您要为该表中的所有可能数据实施的常规更新规则?如果是这样,那么我们需要更多细节。
答案 2 :(得分:0)
硬编码的3
出现两次,会被您想要的许多行所取代。它假设最后3
条记录实际上有值。它接受这些值并按顺序将它们应用于具有空值的记录集。
update a
set value = x.value
from (
select nullRows.id, lastRows.value
from ( select id, value
,(row_number() over(order by id) - 1) % 3 + 1 AS key
from ( select id, value
from a
order by id desc
limit 3
) x
order by 1
) AS lastRows
,( select id
,(row_number() over(order by id) - 1) % 3 + 1 AS key
from a
where value is null
order by id
) AS nullRows
where lastRows.key = nullRows.key
) x
where a.id = x.id