【问题标题】:Remove n elements from array using start and end index使用开始和结束索引从数组中删除 n 个元素
【发布时间】:2017-06-09 09:44:27
【问题描述】:

我在 Postgres 数据库中有下表:

CREATE TABLE test(
  id SERIAL NOT NULL,
  arr int[] NOT NULL
)

并且该数组包含大约 500k 个元素。

我想知道是否有一种有效的方法来更新arr 列,方法是从给定开始和结束索引的数组中删除一组元素,或者只是要删除的“n 个第一个元素”的数量。

【问题讨论】:

    标签: sql arrays postgresql postgresql-9.4


    【解决方案1】:

    您可以access单个元素或元素范围:

    如果你例如想要删除元素 5 到 8,你可以这样做:

    select arr[1:4]||arr[9:]
    from test;
    

    或作为更新:

    update test
       set arr = arr[1:4]||arr[9:];
    

    要删除“前 n 个元素”,只需在 n+1 个元素之后使用切片,例如删除前 5 个元素:

    select arr[6:]
    from test;
    

    arr[6:] 语法需要 Postgres 9.6 或更高版本,更早的版本需要

    select arr[6:cardinality(arr)]
    from test;
    

    cardinality() 是在 9.4 中引入的,如果您使用的是更旧的版本,您需要:

    select arr[6:array_lengt(arr,1)]
    from test;
    

    【讨论】:

    • 您知道上面提到的update 是否会复制新切片吗?因为我需要对大数组进行频繁的删除。
    • @saloua “新切片的副本”是什么意思?如果您指的是一列,则该列始终是完整的(而不是“部分”)
    • 我在问是否在更新列值时,会不会有原来的数组内容和丢弃切片的新内容。然后,如果数组很大并且我需要并行更新,这将是低效的。
    • 如果你想让它更有效率,不要使用数组,使用适当规范化的一对多关系。
    【解决方案2】:

    您可以使用切片(请参阅8.15.3. Accessing Arrays)。

    create table example 
    as select array[1,2,3,4,5,6,7,8] arr;
    

    删除前 3 个元素:

    select arr[4:8]
    from example;
    
         arr     
    -------------
     {4,5,6,7,8}
    (1 row)
    

    从 4 到 5 删除元素:

    select arr[1:3] || arr[6:8] as arr
    from example;
    
          arr      
    ---------------
     {1,2,3,6,7,8}
    (1 row)
    

    如果数组长度未知,则删除前 5 个元素:

    select arr[6:array_length(arr,1)]
    from example;
    
       arr   
    ---------
     {6,7,8}
    (1 row)
    

    【讨论】:

    • 感谢您的回答,但是如果数组非常大并且我需要经常进行删除,那么更新的效率会有多高。
    • 我认为这是删除元素最有效的方法。
    • @a_horse_with_no_name 在psql 中也对我不起作用我收到错误:在“]”处或附近出现语法错误
    • @saloua:您使用的是哪个 Postgres 版本?这对我有用:imgur.com/a/ZX1e1
    • @saloua:啊,那是9.6引入的
    猜你喜欢
    • 2011-11-12
    • 2021-10-12
    • 1970-01-01
    • 2020-01-07
    • 2021-11-24
    • 1970-01-01
    • 2016-11-07
    • 2018-10-31
    • 1970-01-01
    相关资源
    最近更新 更多