为PostgreSQL中的数千条记录分配顺序位置

时间:2016-09-09 17:53:20

标签: sql ruby-on-rails postgresql

使用Ruby on Rails - 但希望这可以通过PostgreSQL直接解决,我试图将100,000个项目从一个列表移动到另一个列表,同时为每个列表分配一个顺序位置:

列表A(位置不重要):

- item 1, position: nil
- item 2, position: nil
- item 3, position: nil

列表B(位置确实重要):

- item 4, position: 1

结果,我想要:

列表B:

- item 4, position: 1
- item 1, position: 2
- item 2, position: 3
- item 3, position: 4

到目前为止我已经考虑过各种策略:

  1. 每个项目一次SQL查询,但移动100k项目时速度变慢:(
  2. 每个列表动态创建一个SQL序列,但这感觉就像错误的方法,因为我每天都要预计1000个新列表
  3. 整个列表的一个SQL查询,其中使用最大位置设置位置,这可能依赖于SQL循环?
  4. 将问题提取到另一个工具(Redis可能更适合最终解决方案,但我希望首先使用可用工具来探索解决方案)

1 个答案:

答案 0 :(得分:0)

我不完全确定你在这里尝试做什么,但我怀疑序列在这里是最好的选择(但不是动态创建的,几乎总是一个坏主意)。如果您真的不想使用序列,也可以使用window functions并具体使用row_number窗口函数。

这是一个完整的例子。假设您有以下表格和一些示例数据:

CREATE TABLE ListA (
    item integer NOT NULL,
    position integer
);

CREATE TABLE ListB(         item integer NOT NULL,         位置整数     );

INSERT INTO ListA(item) VALUES (1),(2),(3);
INSERT INTO ListB(item,position) VALUES (4,1);

然后,以下查询返回ListA的所有元素,但为其分配了新位置(从1开始):

SELECT item,row_number() OVER (ORDER BY item)
FROM ListA;

如果你想从ListB停止的位置开始,你就可以这样做

SELECT item,row_number() OVER (ORDER BY item)+(SELECT max(position) FROM ListB)
FROM ListA;

最后,要将这些行添加到ListB,您可以这样做:

INSERT INTO ListB(item,position)
SELECT item,row_number() OVER (ORDER BY item)+(SELECT max(position) FROM ListB)
FROM ListA;