ฉันมีอาร์เรย์ประเภทbigint
ฉันจะลบค่าที่ซ้ำกันในอาร์เรย์นั้นได้อย่างไร
เช่น: array[1234, 5343, 6353, 1234, 1234]
ฉันควรจะได้รับ array[1234, 5343, 6353, ...]
ฉันทดสอบตัวอย่างSELECT uniq(sort('{1,2,3,2,1}'::int[]))
ในคู่มือ postgres แต่ใช้งานไม่ได้
ฉันมีอาร์เรย์ประเภทbigint
ฉันจะลบค่าที่ซ้ำกันในอาร์เรย์นั้นได้อย่างไร
เช่น: array[1234, 5343, 6353, 1234, 1234]
ฉันควรจะได้รับ array[1234, 5343, 6353, ...]
ฉันทดสอบตัวอย่างSELECT uniq(sort('{1,2,3,2,1}'::int[]))
ในคู่มือ postgres แต่ใช้งานไม่ได้
คำตอบ:
ฉันต้องเผชิญกับสิ่งเดียวกัน แต่อาร์เรย์ในกรณีของฉันถูกสร้างขึ้นผ่านarray_agg
ฟังก์ชัน และโชคดีที่อนุญาตให้รวมค่าDISTINCTเช่น:
array_agg(DISTINCT value)
สิ่งนี้ใช้ได้กับฉัน
trim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
sort(int[])
และuniq(int[])
ฟังก์ชั่นที่มีให้โดยintarrayโมดูล contrib
ต้องการเปิดใช้งานการใช้งานคุณจะต้องติดตั้งโมดูล
หากคุณไม่ต้องการใช้โมดูลการสนับสนุน intarray หรือหากคุณต้องลบรายการที่ซ้ำกันออกจากอาร์เรย์ประเภทต่างๆคุณมีอีกสองวิธี
หากคุณมี PostgreSQL 8.4 เป็นอย่างน้อยคุณสามารถใช้ประโยชน์จากunnest(anyarray)
ฟังก์ชันได้
SELECT ARRAY(SELECT DISTINCT UNNEST('{1,2,3,2,1}'::int[]) ORDER BY 1);
?column?
----------
{1,2,3}
(1 row)
หรือคุณสามารถสร้างฟังก์ชันของคุณเองเพื่อทำสิ่งนี้
CREATE OR REPLACE FUNCTION array_sort_unique (ANYARRAY) RETURNS ANYARRAY
LANGUAGE SQL
AS $body$
SELECT ARRAY(
SELECT DISTINCT $1[s.i]
FROM generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
ORDER BY 1
);
$body$;
นี่คือตัวอย่างการเรียกร้อง:
SELECT array_sort_unique('{1,2,3,2,1}'::int[]);
array_sort_unique
-------------------
{1,2,3}
(1 row)
... ในกรณีที่statandardห้องสมุด (?) สำหรับชนิดของนี้ยูทิลิตี้อาร์เรย์ _X ??
ลองค้นหาดู ... ดูบ้าง แต่ไม่มีมาตรฐาน:
postgres.cz/wiki/Array_based_functions : ข้อมูลอ้างอิงที่ดี!
JDBurnZ / postgresql-anyarray เป็นความคิดริเริ่มที่ดี แต่ต้องการการทำงานร่วมกันเพื่อปรับปรุง
wiki.postgresql.org/Snippetsความคิดริเริ่มที่น่าผิดหวัง แต่ "วิกินอกระบบ" ต้องการการทำงานร่วมกันเพื่อปรับปรุง
MADlib : ดี! .... แต่มันคือช้างไม่ใช่ "pure SQL snippets lib"
array_distinct()
ฟังก์ชัน snippet-lib ที่ง่ายและเร็วกว่านี่คือการใช้งานที่ง่ายที่สุดและอาจเร็วกว่าสำหรับarray_unique()
หรือarray_distinct()
:
CREATE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x) FROM unnest($1) t(x);
$f$ LANGUAGE SQL IMMUTABLE;
หมายเหตุ: ทำงานได้ตามที่คาดไว้กับประเภทข้อมูลยกเว้นอาร์เรย์อาร์เรย์
SELECT array_distinct( array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99] ),
array_distinct( array['3','3','hello','hello','bye'] ),
array_distinct( array[array[3,3],array[3,3],array[3,3],array[5,6]] );
-- "{1,2,3,4,6,8,99}", "{3,bye,hello}", "{3,5,6}"
"ผลข้างเคียง" คือการระเบิดอาร์เรย์ทั้งหมดในชุดขององค์ประกอบ
PS: ด้วยอาร์เรย์ JSONB ทำงานได้ดี
SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] );
-- "{"[3, 3]","[5, 6]"}"
แก้ไข: พารามิเตอร์ "drop nulls" ที่ซับซ้อนกว่า แต่มีประโยชน์
CREATE FUNCTION array_distinct(
anyarray, -- input array
boolean DEFAULT false -- flag to ignore nulls
) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x)
FROM unnest($1) t(x)
WHERE CASE WHEN $2 THEN x IS NOT NULL ELSE true END;
$f$ LANGUAGE SQL IMMUTABLE;
ผมได้รวบรวมชุดของวิธีการจัดเก็บ (ฟังก์ชั่น) การขาดการต่อสู้ของ PostgreSQL anyarray
ของอาร์เรย์งานกับประกาศเกียรติคุณ ฟังก์ชั่นเหล่านี้ได้รับการออกแบบมาเพื่อทำงานกับข้อมูลอาร์เรย์ทุกประเภทไม่ใช่แค่จำนวนเต็มเหมือนที่ intarray ทำ: https://www.github.com/JDBurnZ/anyarray
anyarray_uniq.sql
ในกรณีของคุณทั้งหมดที่คุณต้องการจริงๆจำเป็นต้องเป็น คัดลอกและวางเนื้อหาของไฟล์นั้นลงในแบบสอบถาม PostgreSQL และดำเนินการเพื่อเพิ่มฟังก์ชัน anyarray_sort.sql
หากคุณต้องการอาร์เรย์เรียงลำดับเช่นกันนอกจากนี้ยังเพิ่ม
จากนั้นคุณสามารถสร้างแบบสอบถามง่ายๆดังนี้:
SELECT ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234])
ส่งคืนสิ่งที่คล้ายกับ: ARRAY[1234, 6353, 5343]
หรือหากคุณต้องการการจัดเรียง:
SELECT ANYARRAY_SORT(ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234]))
กลับตรง: ARRAY[1234, 5343, 6353]
การใช้DISTINCT
เรียงลำดับอาร์เรย์โดยปริยาย หากต้องรักษาลำดับสัมพัทธ์ขององค์ประกอบอาร์เรย์ในขณะที่ลบรายการที่ซ้ำกันฟังก์ชันสามารถออกแบบได้ดังต่อไปนี้: (ควรใช้งานได้ตั้งแต่ 9.4 เป็นต้นไป)
CREATE OR REPLACE FUNCTION array_uniq_stable(anyarray) RETURNS anyarray AS
$body$
SELECT
array_agg(distinct_value ORDER BY first_index)
FROM
(SELECT
value AS distinct_value,
min(index) AS first_index
FROM
unnest($1) WITH ORDINALITY AS input(value, index)
GROUP BY
value
) AS unique_input
;
$body$
LANGUAGE 'sql' IMMUTABLE STRICT;
นี่คือวิธี "แบบอินไลน์":
SELECT 1 AS anycolumn, (
SELECT array_agg(c1)
FROM (
SELECT DISTINCT c1
FROM (
SELECT unnest(ARRAY[1234,5343,6353,1234,1234]) AS c1
) AS t1
) AS t2
) AS the_array;
อันดับแรกเราสร้างชุดจากอาร์เรย์จากนั้นเราเลือกเฉพาะรายการที่แตกต่างกันจากนั้นรวมกลับเข้าสู่อาร์เรย์
SELECT array_agg(DISTINCT c1) FROM unnest(ARRAY[1234,5343,6353,1234,1234]) t(c1)
ในแบบสอบถามเดียวฉันทำสิ่งนี้:
SELECT (select array_agg(distinct val) from ( select unnest(:array_column) as val ) as u ) FROM :your_table;
สำหรับคนอย่างฉันที่ยังต้องจัดการกับ postgres 8.2 ฟังก์ชันการเรียกซ้ำนี้สามารถกำจัดรายการที่ซ้ำกันได้โดยไม่ต้องแก้ไขการเรียงลำดับของอาร์เรย์
CREATE OR REPLACE FUNCTION my_array_uniq(bigint[])
RETURNS bigint[] AS
$BODY$
DECLARE
n integer;
BEGIN
-- number of elements in the array
n = replace(split_part(array_dims($1),':',2),']','')::int;
IF n > 1 THEN
-- test if the last item belongs to the rest of the array
IF ($1)[1:n-1] @> ($1)[n:n] THEN
-- returns the result of the same function on the rest of the array
return my_array_uniq($1[1:n-1]);
ELSE
-- returns the result of the same function on the rest of the array plus the last element
return my_array_uniq($1[1:n-1]) || $1[n:n];
END IF;
ELSE
-- if array has only one item, returns the array
return $1;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
สำหรับตัวอย่าง:
select my_array_uniq(array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99]);
จะให้
{3,8,2,6,4,1,99}