2012-10-29 23 views
43

यदि मैं नाम एकत्र करने के लिए array_agg का उपयोग करता हूं, तो मुझे अपने नाम अल्पविराम से अलग करते हैं, लेकिन यदि null मान है, तो उस नल को कुल में एक नाम के रूप में भी लिया जाता है। उदाहरण के लिए:postgres का उपयोग कर string_agg में array_agg में शून्य मानों को कैसे बाहर निकालना है?

SELECT g.id, 
     array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users, 
     array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users 
FROM groups g 
GROUP BY g.id; 

यह सिर्फ Larry,Phil (मेरी 9.1.2, यह NULL,Larry,Phil से पता चलता में) के बजाय ,Larry,Phil देता है। this बेला में के रूप में

इसके बजाय, अगर मैं string_agg() उपयोग करते हैं, यह मुझे केवल नाम (खाली अल्पविराम या nulls के बिना) here

समस्या

तरह से पता चलता है कि मैं सर्वर पर स्थापित Postgres 8.4 है, और string_agg() नहीं करता ' वहाँ काम नहीं करते हैं। string_agg() के समान array_agg काम करने का कोई तरीका है?

+0

ज्यादा इस विषय पर इस PostgreSQL मेलिंग सूची धागा देखें: http://postgresql.1045698.n5.nabble.com/array-agg-NULL-Handling-td2798942.html –

+0

मैं माफी चाहता हूँ, मैं डॉन ' टी लगता है कि उस धागे में कोई समाधान नहीं है .. – Daud

+0

उस धागे में दो समाधान हैं। एक एक समारोह बनाना है और दूसरा (सिर्फ सुझाव नहीं दिया गया है) मैंने जवाब दिया है। –

उत्तर

16

SQL Fiddle

select 
    id, 
    (select array_agg(a) from unnest(canonical_users) a where a is not null) canonical_users, 
    (select array_agg(a) from unnest(non_canonical_users) a where a is not null) non_canonical_users 
from (
    SELECT g.id, 
      array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users, 
      array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users 
    FROM groups g 
    GROUP BY g.id 
) s 

या, सरल और सस्ता हो सकता है, array_to_string जो nulls समाप्त का उपयोग कर:

SELECT 
    g.id, 
    array_to_string(
     array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) 
     , ',' 
    ) canonical_users, 
    array_to_string(
     array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) 
     , ',' 
    ) non_canonical_users 
FROM groups g 
GROUP BY g.id 

SQL Fiddle

+1

यह काम नहीं करेगा। कृपया प्रदान किए गए पहेली में इसे आज़माएं .. – Daud

+0

धन्यवाद। लेकिन यदि मुख्य प्रश्न 1000 पंक्तियों को लौटाता है, तो 2 सबक्वायरीज़ (अनन्य का उपयोग करके) प्रत्येक पंक्ति के लिए एक बार दौड़ेंगे .. क्या 2000 अतिरिक्त चयन प्रश्नों को निष्पादित करने से एनयूएलएल को सहन करना बेहतर होगा? – Daud

+0

@Daud नया संस्करण जो सस्ता हो सकता है। सुनिश्चित करने के लिए दोनों की व्याख्या आउटपुट लें। –

3

टिप्पणियां आप एक लिख सकते हैं में सुझाव दिया गया है के रूप में एक सरणी में nulls को बदलने के लिए समारोह, हालांकि जुड़े धागे में भी बताया टिप्पणियों में, इस तरह की कुल कार्य की दक्षता को हरा देता है यदि आपको कुल मिलाकर बनाना है, तो इसे विभाजित करें और फिर इसे फिर से एकत्र करें।

मुझे लगता है कि सरणी में नल रखना रखना Array_Agg की केवल एक (शायद अवांछित) विशेषता है। आप इस से बचने के लिए सबक्वेरी इस्तेमाल कर सकते हैं:

SELECT COALESCE(y.ID, n.ID) ID, 
     y.Users, 
     n.Users 
FROM ( SELECT g.ID, ARRAY_AGG(g.Users) AS Users 
      FROM Groups g 
      WHERE g.Canonical = 'Y' 
      GROUP BY g.ID 
     ) y 
     FULL JOIN 
     ( SELECT g.ID, ARRAY_AGG(g.Users) AS Users 
      FROM Groups g 
      WHERE g.Canonical = 'N' 
      GROUP BY g.ID 
     ) n 
      ON n.ID = y.ID 

SQL FIDDLE

+0

धन्यवाद। लेकिन मुझे किसी दिए गए समूह के भीतर पंक्तियों को संभालने के लिए 'केस' की आवश्यकता थी, और सबक्वायरी – Daud

-3

एक बड़ा सवाल यह है कि क्यों एक बार में सभी उपयोगकर्ता/समूह कॉम्बो खींच। गारंटी है कि आपके यूआई सभी डेटा को संभाल नहीं सकते हैं। बड़े पैमाने पर डेटा में पेजिंग जोड़ना भी एक बुरा विचार है। डेटा देखने से पहले अपने उपयोगकर्ताओं को सेट फ़िल्टर करने के लिए प्राप्त करें। सुनिश्चित करें कि आपका जॉइन विकल्प सेट सूची में है ताकि वे प्रदर्शन के लिए फ़िल्टर कर सकें यदि वे चाहते हैं। कभी-कभी 2 प्रश्न उपयोगकर्ता को खुश करते हैं यदि वे दोनों तेज़ होते हैं।

10

सरणी समेकन से नल को हटाने के सामान्य प्रश्न को हल करने में समस्या पर हमला करने के दो मुख्य तरीके हैं: या तो array_agg (unnest (array_agg (x)) या कस्टम समग्र बनाना।

प्रथम रूप above से पता चला की है:

SELECT 
    array_agg(u) 
FROM (
    SELECT 
     unnest(
      array_agg(v) 
     ) as u 
    FROM 
     x 
    ) un 
WHERE 
    u IS NOT NULL; 

दूसरा:

/* 
With reference to 
http://ejrh.wordpress.com/2011/09/27/denormalisation-aggregate-function-for-postgresql/ 
*/ 
CREATE OR REPLACE FUNCTION fn_array_agg_notnull (
    a anyarray 
    , b anyelement 
) RETURNS ANYARRAY 
AS $$ 
BEGIN 

    IF b IS NOT NULL THEN 
     a := array_append(a, b); 
    END IF; 

    RETURN a; 

END; 
$$ IMMUTABLE LANGUAGE 'plpgsql'; 

CREATE AGGREGATE array_agg_notnull(ANYELEMENT) (
    SFUNC = fn_array_agg_notnull, 
    STYPE = ANYARRAY, 
    INITCOND = '{}' 
); 

कॉलिंग दूसरा (स्वाभाविक रूप से) है एक छोटे से अच्छे पहले से देख:

एक्स से array_agg_notnull (v) का चयन करें;

5

मैं यह जोड़ रहा हूं, भले ही यह धागा काफी पुराना हो, लेकिन मैं इस साफ चाल में भाग गया जो छोटे सरणी पर काफी अच्छी तरह से काम करता है। यह अतिरिक्त पुस्तकालयों या कार्यों के बिना पोस्टग्रेस 8.4+ पर चलता है।

string_to_array(array_to_string(array_agg(my_column)))::int[] 

array_to_string() विधि वास्तव में nulls से छुटकारा मिलता है।

122

postgresql-9.3 के साथ कोई यह कर सकता है;

SELECT g.id, 
    array_remove(array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END), NULL) canonical_users, 
    array_remove(array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END), NULL) non_canonical_users 
FROM groups g 
GROUP BY g.id; 

अद्यतन: PostgreSQL-9.4 के साथ;

SELECT g.id, 
    array_agg(g.users) FILTER (WHERE g.canonical = 'Y') canonical_users, 
    array_agg(g.users) FILTER (WHERE g.canonical = 'N') non_canonical_users 
FROM groups g 
GROUP BY g.id; 
+3

अक्षम होंगे, यह काम करता है और तेज़ और सुरुचिपूर्ण है, इसने मुझे ओपी के समान समस्या हल कर दी है। उन लोगों के लिए 9.3 तक अपग्रेड करने का एक कारण जिन्होंने अभी तक ऐसा नहीं किया है। +1 –

+6

9.4 और भी सुरुचिपूर्ण है। एक आकर्षण की तरह काम करता है – jmgarnier

+0

9.4 संस्करण भी बेहतर है, क्योंकि मुझे अपने मामले में दूर फ़िल्टर करने की आवश्यकता है जो नल है। – coladict