使用当前项目索引更新行

时间:2018-11-05 08:27:21

标签: postgresql

我有这张桌子:

+------+----------+
| id   | position |
+------+----------+
| 1    | 38       |
+------+----------+
| 5    | 102      |
+------+----------+
| 12   | 112      |
+------+----------+
| 13   | 142      |
+------+----------+

并希望按如下方式“重新平衡”排名栏

+------+----------+
| id   | position |
+------+----------+
| 1    | 0        | (i=0 * 128)
+------+----------+
| 5    | 128      | (i=1 * 128)
+------+----------+
| 12   | 256      | (i=2 * 128)
+------+----------+
| 13   | 384      | (i=3 * 128)
+------+----------+

我也将职位定位在这样的列表中:

+------+---------------------+
| id   | list_id  | position |
+------+---------------------+
| 1    | 1        | 10       |
+------+---------------------+
| 5    | 1        | 22       |
+------+----------+----------+
| 12   | 2        | 8        |
+------+----------+----------+
| 13   | 2        | 18       |
+------+----------+----------+

我想我需要知道SQL更新语句中当前项目的索引,或者使用子查询?

您将如何去做?

1 个答案:

答案 0 :(得分:1)

demo: db<>fiddle

UPDATE mytable
SET position = s.new_position
FROM (
    SELECT 
        id, 
        (row_number() over (ORDER BY id) - 1) * 128 as new_position
    FROM mytable
) s
WHERE mytable.id = s.id;

使用window function row_number可以将行计数添加到数据集(如果您希望将其称为“索引”)。它以1开头,所以我减去1再乘以128。


更新的问题(在第三张表中添加了list_id

如果要对每个列表进行单独的位置计数,则必须在窗口功能(PARTITION BY list_id)中添加一个窗口框架:

UPDATE mytable
SET position = s.new_position
FROM (
    SELECT 
        id, 
        (row_number() over (PARTITION BY list_id ORDER BY id) - 1) * 128 as new_position
    FROM mytable
) s
WHERE mytable.id = s.id;

结果为:

id   list_id   position
1    1         0
5    1         128
12   2         0
13   2         128

demo:db<>fiddle