简体   繁体   English

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

[英]Assign sequential positions to thousands of records in PostgreSQL

Using Ruby on Rails —but hopefully this can be solved via PostgreSQL directly, I'm trying to move 100,000 items from one list to another, while assigning each of them a sequential position: 使用Ruby on Rails-但希望可以通过PostgreSQL直接解决,我试图将100,000个项目从一个列表移动到另一个列表,同时为每个列表分配一个顺序的位置:

List A (where position don't matter): 清单A(位置无关紧要):

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

List B (where positions do matter): 清单B(职位很重要):

- item 4, position: 1

And as a result, I want: 结果,我想要:

List B: 清单B:

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

Various strategies I've thought about so far: 到目前为止,我考虑过的各种策略:

  1. one SQL query per item, but this gets slow when moving 100k items :( 每个项目一个SQL查询,但是移动10万个项目时,它会变慢:(
  2. dynamically creating one SQL sequence per list, but this feels like the wrong approach as I'm expecting 1000 new lists per day 动态地为每个列表创建一个SQL序列,但这感觉像是错误的方法,因为我希望每天有1000个新列表
  3. one SQL query for the whole list where the position is set using the max position, which would probably rely on a SQL loop? 一个SQL查询整个列表,其中使用最大位置设置位置,这可能取决于SQL循环?
  4. extracting the problem to a different tool (Redis might be better suited for the end solution, but I'd like to explore solutions with available tools first) 将问题提取到其他工具(Redis可能更适合最终解决方案,但我想先使用可用工具探索解决方案)

I am not entirely sure what are you trying to do here, but I suspect that sequences would be the best option here (but not dynamically created ones, that almost always a bad idea). 我不确定您要在这里做什么,但是我怀疑序列是这里的最佳选择(但不是动态创建的序列,这几乎总是一个坏主意)。 If you really don't want to use sequences, you could also use window functions and specificaly the row_number windows function. 如果您确实不想使用序列,则还可以使用窗口函数 ,特别是row_number窗口函数。

Here's a complete example. 这是一个完整的例子。 Suppose that you have the following tables with some sample data: 假设您具有包含一些示例数据的下表:

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

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

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

Then the following query returns all elements of ListA but with a new position assigned to them (starting from 1): 然后,以下查询返回ListA所有元素,但是ListA分配了新位置(从1开始):

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

If you would like to start the position numbers from where ListB stops, you can do it like that 如果您想从ListB停止的位置开始位置编号,则可以这样做

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

Finally, to add those rows to ListB , you can do that like so: 最后,要将这些行添加到ListB ,您可以像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM