पोस्टग्रेज में डुप्लिकेट सरणी मानों को समाप्त करें


86

मेरे पास एक प्रकार की सरणी है bigint, मैं उस सरणी में डुप्लिकेट मान कैसे निकाल सकता हूं?

उदाहरण के लिए: array[1234, 5343, 6353, 1234, 1234]

मुझे मिलना चाहिए array[1234, 5343, 6353, ...]

मैंने SELECT uniq(sort('{1,2,3,2,1}'::int[]))पोस्टग्रेज मैनुअल में उदाहरण का परीक्षण किया लेकिन यह काम नहीं कर रहा है।

जवाबों:


92

मैंने उसी का सामना किया। लेकिन मेरे मामले में एक सरणी array_aggफ़ंक्शन के माध्यम से बनाई गई है। और सौभाग्य से यह DISTINCT मानों को एकत्र करने की अनुमति देता है , जैसे:

  array_agg(DISTINCT value)

यह मेरे लिए काम करता है।


5
ध्यान दें कि DISTINCT विंडो कार्यों के लिए समर्थित नहीं है।
विचारशील

tks guytrim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
फैबियो जांगिरोलमी

4
array_agg (DISTINCT Array [1,2,2,3]) चुनें "{{1,2,2,3}}"
user48956

@ user48956, जो तर्कसंगत है, जैसे ही आप एक सरणी को मान के रूप में दर्ज करते हैं, आपको एक एकल स्तंभ को मान के रूप में सेट करने की आवश्यकता होती है जिसे क्वेरी में समूहीकृत किया जाता है
Daniël Tulp

83

sort(int[])और uniq(int[])कार्यों द्वारा प्रदान की जाती हैं 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)

1
समस्या का समाधान ("डुप्लिकेट सरणी मान को समाप्त करें") को सॉर्ट करने की आवश्यकता नहीं है । यद्यपि आमतौर पर एक उपयोगी विशेषता है, यह इस संदर्भ / आवश्यकता में अनावश्यक (सीपीयू लागत) है।
पीटर क्रूस

27

... कहाँ इस तरह के array_X उपयोगिता के लिए सांख्यिकीय पुस्तकालयों (?) ??

खोजने का प्रयास करें ... कुछ देखें लेकिन कोई मानक नहीं:

  • postgres.cz/wiki/Array_based_functions : अच्छा संदर्भ!

  • JDBurnZ / postgresql-anyarray , अच्छी पहल लेकिन बढ़ाने के लिए कुछ सहयोग की आवश्यकता है।

  • wiki.postgresql.org/Snippets , निराश पहल, लेकिन "ऑफिशियल विकी" को बढ़ाने के लिए कुछ सहयोग की आवश्यकता है।

  • मुदलिब : अच्छा! .... लेकिन यह एक हाथी है, "शुद्ध एसक्यूएल स्निपेट्स लिबास" नहीं।


सरलतम और तेज़ array_distinct()स्निपेट-लिब फ़ंक्शन

के लिए सबसे आसान और शायद तेजी से कार्यान्वयन यहाँ के 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}"

"साइड इफेक्ट" तत्वों के एक सेट में सभी सरणियों को विस्फोट करना है।

पुनश्च: JSONB सरणियों के साथ ठीक काम करता है,

SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] );
 -- "{"[3, 3]","[5, 6]"}"

संपादित करें: अधिक जटिल लेकिन उपयोगी, एक "ड्रॉप नल" पैरामीटर

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;

क्या आप यह बता सकते हैं कि TROM (x) FROM ($ 1) t (x) में क्या कर रहा है ... यह भी कि मैं उन वस्तुओं के क्रम को कैसे रख सकता हूँ जिनमें उन्होंने डाला
abhirathore2006

@ abhirathore2006 यह उत्तर एक विकी है, आप अपने द्वारा सुझाए गए स्पष्टीकरण लिख सकते हैं। "ऑर्डर रखें" के बारे में, नहीं, यह एक विनाशकारी समाधान है, मूल सरणी क्रम को संरक्षित करने के लिए इस पृष्ठ में PLpgSQL समाधान देखें। यह दो आवश्यकताओं, क्रमबद्ध और विशिष्ट है ( मुख्य उत्तर की सक्सेज देखें और वहां मेरी टिप्पणी)।
पीटर क्रस

कोई चिंता नहीं, मैं पहले से ही कहीं और से समाधान मिल गया, हाँ कि plsql समाधान है
abhirathore2006

13

मैंने पोस्टग्रेएसक्यूएल की कमी से निपटने के लिए संग्रहीत प्रक्रियाओं (कार्यों) के एक सेट को संभाला है जो कि संभाले गए सरणी हैंडलिंग की कमी है anyarray। ये फ़ंक्शन किसी भी सरणी डेटा-प्रकार पर काम करने के लिए डिज़ाइन किए गए हैं, न कि केवल पूर्णांक के रूप में इंटेरियर करता है: 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]


13

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;

1
सबसे बढ़िया उत्तर! इसे भी देखें: dba.stackexchange.com/questions/211501/…
fjsj

9

यहाँ "इनलाइन" तरीका है:

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;

पहले हम सरणी से एक सेट बनाते हैं, फिर हम केवल विशिष्ट प्रविष्टियों का चयन करते हैं, और फिर इसे सरणी में वापस एकत्रित करते हैं।


9
या "अधिक इनलाइन" ;-) SELECT array_agg(DISTINCT c1) FROM unnest(ARRAY[1234,5343,6353,1234,1234]) t(c1)
पीटर क्रस


3

मेरे जैसे लोगों के लिए जिन्हें अभी भी like.२ पोस्टग्रेट्स से निपटना है, यह पुनरावर्ती कार्य सरणी के प्रकार में बदलाव के बिना डुप्लिकेट को समाप्त कर सकता है।

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}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.