2010-01-15 20 views
25

pgSQL'deki bir diziden bir değeri kaldırmanın bir yolu var mı? Ya da daha kesin olmak gerekirse, son değeri patlatmak için? this list'a göre yargılama yanıtı yok gibi görünüyor. İstediğim sonucu ek bir indeks işaretçisi ile elde edebilirim, ama biraz hantal.pgSQL içinde dizi değerlerini kaldır

cevap

12

Hayır, yapabileceğinizi düşünmüyorum. En azından böyle çirkin bir şey yazmadan:

SELECT ARRAY (
SELECT UNNEST(yourarray) LIMIT (
    SELECT array_upper(yourarray, 1) - 1 
) 
) 
+0

tarihinde bana ne anlatıyor bakılırsa, bu gibi görünüyor ben olamaz.Birisi size yanlış olduğunu kanıtlamadığı sürece bunu kabul edilen cevap olarak işaretleyeceğim :) – oggy

8

Ben senin bağlamda hakkında emin değilim, ama bu size çalışmak için bir şeyler vermelidir: Öyle bir array_pop fonksiyonu oluşturduk

CREATE TABLE test (x INT[]); 
INSERT INTO test VALUES ('{1,2,3,4,5}'); 

SELECT x AS array_pre_pop, 
     x[array_lower(x,1) : array_upper(x,1)-1] AS array_post_pop, 
     x[array_upper(x,1)] AS popped_value 
FROM test; 


array_pre_pop | array_post_pop | popped_value 
---------------+----------------+-------------- 
{1,2,3,4,5} | {1,2,3,4}  |   5 
+0

Teşekkürler, dilimleme tam olarak verimli bir çözüm değil sanırım işe yarayacaktı? – oggy

+0

Bence pop() için yerleşik bir işlev olmadığını düşünürken en iyi yöntemdir. Spesifiklikleri bilmeden, daha iyi bir tavsiyede bulunamam. Belirli bir kaydın içeriği boyunca döngü yapmak istiyorsanız, o zaman() bir dizi kayıt haline dönüşeceği için daha iyi olacaktır. Ancak, dizinin birden çok kayıttaki "son öğelerini" kaldırmak için yalnızca bir tabloyu güncellemek isterseniz, dizinin dilimlenmesi yolu olacaktır. –

2

Bir elemanı bilinen değerden bir diziden kaldırabilirsiniz.

CREATE OR REPLACE FUNCTION array_pop(a anyarray, element character varying) 
RETURNS anyarray 
LANGUAGE plpgsql 
AS $function$ 
DECLARE 
    result a%TYPE; 
BEGIN 
SELECT ARRAY(
    SELECT b.e FROM (SELECT unnest(a)) AS b(e) WHERE b.e <> element) INTO result; 
RETURN result; 
END; 
$function$ 

bir özü versiyonu Burada https://gist.github.com/1392734

5

orada da

CREATE OR REPLACE FUNCTION array_remove_item (array_in INTEGER[], item INTEGER) 
RETURNS INTEGER[] 
LANGUAGE SQL 
AS $$ 
SELECT ARRAY(
    SELECT DISTINCT $1[s.i] AS "foo" 
    FROM GENERATE_SERIES(ARRAY_LOWER($1,1), ARRAY_UPPER($1,1)) AS s(i) 
    WHERE $2 != $1[s.i] 
    ORDER BY foo 
); 
$$; 

Bu tam sayı dizileri için tabii ki, ancak ANYARRAY ANYELEMENT

için modifiye edilebilir bir tam sayı [] diziler için kullanımı bir fonksiyondur
=> select array_remove_item(array[1,2,3,4,5], 3); 
-[ RECORD 1 ]-----+---------- 
array_remove_item | {1,2,4,5} 
14

Son değeri kaldırmanın en kolay yolu:

array1 = array[1,2,3] 
array1 = (select array1[1:array_upper(array1, 1) - 1]) 
+2

Bu kabul edilen cevap olmalı. – Lucian

+0

Evet, cevabı bu - bazı yarı-kolonları ile benim için iyi çalışıyor. – Vidar

9

DÜZ SQL bir diziden bir değer kaldırmak için basit bir yol var:

SELECT unnest('{5,NULL,6}'::INT[]) EXCEPT SELECT NULL 

o diziden tüm NULL değerleri kaldıracaktır. Sonuç olacaktır:

#| integer | 
------------ 
1| 5 | 
2| 6 | 
+0

9.3+ sürümünün kullanıcıları bu yanıtı görmelidir (http://stackoverflow.com/a/27346920/3159183). Sürüm 9.2 ve altındaki kullanıcılar yukarıdaki kodu yukarıdaki gibi yeniden kullanabilirler: http://sqlfiddle.com/#!15/03d32/1/0 – SeldomNeedy

3

Ben 9.2 üzerinde çalışan ve ben bu yürütemez değilim:

update tablename set arrcolumn=arrcolumn[1:array_length(arrcolumn)-1]; 

veya şey aynı tür ön elemanını kapalı kayabilir:

update tablename set arrcolumn=arrcolumn[2:array_length(arrcolumn)]; 

Dikkat edin, programcılar - bilimle ilgili bilinmeyen bir nedenle, pgsql dizileri 0 dizinli yerine 1 dizine eklenir.

0

bu deneyin:

update table_name set column_name=column_name[1:array_upper(column_name, 1)-1]; 
-1

My işlevini diziler her türlü.

Dış fonksiyonu:

CREATE OR REPLACE FUNCTION "outer_array"(anyarray, anyarray) RETURNS anyarray AS $$ 
    SELECT 
     "new"."item" 
    FROM (
     SELECT 
      ARRAY(
       SELECT 
        "arr"."value" 
       FROM (
        SELECT 
         generate_series(1, array_length($1, 1)) AS "i", 
         unnest($1)        AS "value" 
       ) "arr" 
       WHERE 
        "arr"."value" <> ALL ($2) 
       ORDER BY 
        "arr"."i" 
      ) AS "item" 
    ) "new" 
    $$ 
LANGUAGE sql 
IMMUTABLE 
RETURNS NULL ON NULL INPUT 
; 

İç fonksiyonu:

sürümü 9.3 olarak ve yapabileceğiniz yukarıda
CREATE OR REPLACE FUNCTION "inner_array"(anyarray, anyarray) RETURNS anyarray AS $$ 
    SELECT 
     "new"."item" 
    FROM (
     SELECT 
      ARRAY(
       SELECT 
        "arr"."value" 
       FROM (
        SELECT 
         generate_series(1, array_length($1, 1)) AS "i", 
         unnest($1)        AS "value" 
       ) "arr" 
       WHERE 
        "arr"."value" = ANY ($2) 
       ORDER BY 
        "arr"."i" 
      ) AS "item" 
    ) "new" 
$$ 
LANGUAGE sql 
IMMUTABLE 
RETURNS NULL ON NULL INPUT 
; 
55

:

update users set flags = array_remove(flags, 'active') 
+0

2015'ten itibaren, bu en uygun yanıttır. En azından PostgreSQL 9.3 çalıştırıyor. –

+0

Henüz 9.3+ sürümüne geçememiş olanlarınız için, gösterildiği gibi kendi 'array_remove()' yazabilmeniz gerekir: http://sqlfiddle.com/#!15/03d32/1/0 – SeldomNeedy

+0

Bu, kesinlikle "** en uygun cevap" değil, soru "açıkça son değeri" yapıp yapamayacağımızı sorar. Son öğenin değeri için ilk sorgulama yapsanız bile, bu değer dizide hiç yinelenmemişse, ** tüm ** örnekleri kaldırılacaktır. Bu açıkça OP'nin sorduğu bir 'array_pop()' işlevi gibi bir şeyin istenen işlevselliği değildir. – JMTyler

İlgili konular