简体   繁体   English

在缺少数字的序列中插入一个数字

[英]Inserting a number in a sequence with missing numbers

I have a table containing info of tree nodes.我有一个包含树节点信息的表。

element_type_id | root_id | parent_id | number_in_parent
      4             1          1               1
      4             1          1               2
      4             1          1               5
      4             2          66              1
      4             2          66              2
      4             2          66              7

I need to copy all elements from root_id 2 into root_1 .我需要将所有元素从root_id 2 复制到root_1 But, if element_type_id and number matches, the inserting element must be renumbered into a minimal free number of sequence 1..99.但是,如果element_type_idnumber匹配,则插入元素必须重新编号为序列 1..99 的最小空闲数。 For example: the first one has numbers 1,2,5.例如:第一个有数字 1,2,5。 The second one - 1,2,3.第二个 - 1,2,3。 The result must be 1,2,3,4,5,7.结果必须是 1,2,3,4,5,7。

To generate "free numbers" i could do like this:要生成“免费号码”,我可以这样做:

SELECT "number" FROM (
    SELECT generate_series(1, (
        SELECT MAX("number") + 99 as "number" 
        FROM tree_elements te2
        WHERE root_id = 1 AND element_type_id = 4)) AS "number"
        EXCEPT SELECT "number" 
               FROM tree_elements te
               WHERE root_id = 1 AND element_type_id = 4
) s
ORDER BY "number" LIMIT 99;

But I don't realize how to get it work within copy query (whatever it is. cause i don't know that either).但我不知道如何让它在复制查询中工作(不管它是什么。因为我也不知道)。

How do I do that?我怎么做? How to solve the problem by using PostgreSQL?如何使用 PostgreSQL 解决问题? Which way to dig?用什么方法挖? Does PostgreSQL have similar functions? PostgreSQL有类似的功能吗? Or may be I have to use loops, inner loops etc.?或者我可能必须使用循环、内循环等?

I'll present the following, it does not reproduce you requested result exactly, but it does satisfy the "minimal free number of sequence" requirement.我将介绍以下内容,它不会准确地重现您请求的结果,但它确实满足“最小自由序列数”的要求。 Which by-the-way your request does not if your intent is creating a dense sequence.顺便说一句,如果您的意图是创建密集序列,则您的请求不会。
It builds 2 CTEs, avail_numbers and merge_numbers: Avail_numbers starts with "free numbers" generator taking these as cardinal values, it then appends to this set a ordinal number indicating the sequence the cardinal numbers are to be assigned.它构建了 2 个 CTE,avail_numbers 和 merge_numbers:Avail_numbers 以“空闲数字”生成器开始,将它们作为基值,然后在该集合中附加一个序数,指示要分配基数的顺序。 Ie the generator produces produces a set 3,4,6, ... The ordinal assignment transforms this into a set (1,3), (2,4), (3,6).即生成器产生一个集合 3,4,6, ... 序数分配将其转换为一个集合 (1,3), (2,4), (3,6)。 Meaning the first value to use is 3, the second value to use in 4, etc. Merge_numbers is built in a similar fashion, extracting the existing "numbers" as cardinal values and generating ordinals resulting in sets as (1,1),(2,2),(3,7)...这意味着要使用的第一个值是 3,使用 4 中的第二个值等。 Merge_numbers 以类似的方式构建,将现有的“数字”提取为基值并生成序数,结果集为 (1,1),( 2,2),(3,7)...
These sets are then joined on the ordinals producing the set (3,1),(4,2),(7,6) meaning on the merging set update to 3 where current value is 1... (this is where the difference to requested comes in as it update "number" from 7 to 6.然后将这些集合连接到序数上,生成集合 (3,1),(4,2),(7,6),这意味着在合并集合更新为 3 时,当前值为 1...(这就是差异的地方当它把“数字”从 7 更新到 6 时,to requested 进来了。

with avail_numbers(avail_ordinal ,avail_number) as 
   ( select row_number() over(), number_in_parent 
       from ( select number_in_parent 
                from ( select generate_series(1, ( select max(number_in_parent) + 99 as number_in_parent 
                                                     from tree_elements  
                                                    where root_id = 1 
                                                      and element_type_id = 4
                                                 )
                                             ) as number_in_parent
                       except 
                       select number_in_parent 
                         from tree_elements te
                        where root_id = 1 and element_type_id = 4
                     ) s
               order by number_in_parent limit 99
            ) n
   ) 
   , merge_numbers (merge_ordinal , number_in_parent) as 
   ( select row_number() over(),number_in_parent 
       from ( select number_in_parent
                from tree_elements 
               where root_id = 2
                 and element_type_id = 4
               order by number_in_parent
            ) m
   )   
update tree_elements te 
   set root_id = 1
     , number_in_parent = mseq.avail_number 
  from (select mn.number_in_parent,an.avail_number 
          from avail_numbers  an
          join merge_numbers  mn
            on (an.avail_ordinal  = mn.merge_ordinal )
       ) mseq
 where root_id = 2
   and element_type_id = 4
   and te.number_in_parent = mseq.number_in_parent;

There is another issue however.然而还有另一个问题。 What happens when the total rows in the 2 root_id,element_type_id combination is 100 or greater.当 2 root_id,element_type_id 组合中的总行数为 100 或更大时会发生什么。

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

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