目前在表中有这个:
+----+--------+--------------+------------------+
| id | site | location_ids | current_location |
+----+--------+--------------+------------------+
| 1 | google | [1,2,3] | 2 |
| 2 | yahoo | [2,3] | 3 |
| 3 | reddit | [1] | 1 |
| 4 | stack | [1,2,4] | 2 |
+----+--------+--------------+------------------+
我想要做的是批量更新查询,它会将当前位置更新为数组中的下一个项目,或者,如果我们已到达数组的末尾,则重置为第一个项目。
我目前正在手动执行此操作并在我的应用程序中构建逻辑:
update checks as chk set
current_location = c.current_location
from (values
(1, 3),
(2, 2),
(3, 1),
(4, 4)
) as c(id, current_location)
where c.id = chk.id
答案 0 :(得分:4)
其他海报使用的案例表达式可以用mod
函数替换为稍短的解决方案:
UPDATE checks
SET current_location = location_ids[
array_position(location_ids, current_location) % cardinality(location_ids) + 1
]
答案 1 :(得分:2)
可能有一种更好的方式来编写它不涉及调用array_position
两次,但是如果你使用PG 9.5(对于array_position函数)你可以这样做:
UPDATE your_table
SET current_location = location_ids[CASE WHEN array_length(location_ids, 1) = array_position(location_ids, current_location) THEN 1 ELSE array_position(location_ids, current_location) + 1 END];
因此它得到current_location
的索引并检查它是否在数组的末尾。如果是,则获取索引1处的值(PG中的数组索引是从1开始的)。如果不是,则获得该位置的值+ 1。
答案 2 :(得分:2)
我假设Postgres 9.5或更高的答案:
您可以使用array_position(location_ids, current_location)
找到当前位置ID的索引。下一个位置ID应该是下一个索引处的ID,除非该索引大于数组的长度。这可以放在一个表达式中:
case
when
array_position(location_ids, current_location) + 1 > cardinality(location_ids)
then 1
else array_position(location_ids, current_location) + 1
end
此表达式可以直接用于更新语句:
update checks
set current_location =
location_ids[case
when array_position(location_ids, current_location) + 1 > cardinality(location_ids)
then 1
else array_position(location_ids, current_location) + 1
end];