इस समय कोई अंतर्निहित तरीका नहीं है।
सरणी के रूप में
यदि आप उन्हें सहेजने पर लगातार सामान्य करते हैं तो आप सरणी को सेट के रूप में हमेशा क्रमबद्ध और डी-डुप्लिकेट करके संग्रहीत कर सकते हैं। यह बहुत अच्छा होगा यदि PostgreSQL के पास ऐसा करने के लिए एक अंतर्निहित C फ़ंक्शन हो, लेकिन ऐसा नहीं है। मैंने एक लिखने पर एक नज़र डाली लेकिन सी सरणी एपीआई भयानक . है , इसलिए भले ही मैंने एक्सटेंशन का एक गुच्छा लिखा है, लेकिन मैंने अभी सावधानी से इसका समर्थन किया है।
यदि आपको मामूली icky प्रदर्शन से कोई आपत्ति नहीं है तो आप इसे SQL में कर सकते हैं:
CREATE OR REPLACE FUNCTION array_uniq_sort(anyarray) RETURNS anyarray AS $$
SELECT array_agg(DISTINCT f ORDER BY f) FROM unnest($1) f;
$$ LANGUAGE sql IMMUTABLE;
फिर कॉल में सभी सेव को array_uniq_sort
. पर रैप करें या इसे ट्रिगर के साथ लागू करें। फिर आप समानता के लिए अपने सरणी की तुलना कर सकते हैं। आप array_uniq_sort
. से बच सकते हैं ऐप से डेटा के लिए कॉल करता है यदि आपने इसके बजाय ऐप साइड पर सिर्फ सॉर्ट/अद्वितीय किया है।
अगर आप ऐसा करते हैं कृपया अपने "सेट" को सरणी कॉलम के रूप में संग्रहीत करें, जैसे text[]
, अल्पविराम- या स्थान-सीमांकित पाठ नहीं। देखें यह सवाल
कुछ कारणों से।
आपको कुछ चीजों के लिए देखने की जरूरत है, जैसे तथ्य यह है कि सरणी के बीच कास्ट उनके मूल प्रकारों के बीच की तुलना में कठोर हैं। उदा.:
regress=> SELECT 'a' = 'a'::varchar, 'b' = 'b'::varchar;
?column? | ?column?
----------+----------
t | t
(1 row)
regress=> SELECT ARRAY['a','b'] = ARRAY['a','b']::varchar[];
ERROR: operator does not exist: text[] = character varying[]
LINE 1: SELECT ARRAY['a','b'] = ARRAY['a','b']::varchar[];
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
regress=> SELECT ARRAY['a','b']::varchar[] = ARRAY['a','b']::varchar[];
?column?
----------
t
(1 row)
ऐसे कॉलम सरणी-युक्त या सरणी-ओवरलैप जैसे संचालन के लिए GiST-अनुक्रमणीय हैं; सरणी अनुक्रमण पर PostgreSQL दस्तावेज़ देखें।
सामान्यीकृत पंक्तियों के रूप में
दूसरा विकल्प सामान्यीकृत पंक्तियों को उपयुक्त कुंजी के साथ स्टोर करना है। मैं अब भी array_agg
का उपयोग करूंगा/करूंगी उन्हें छांटने और उनकी तुलना करने के लिए, क्योंकि SQL सेट संचालन इसके लिए उपयोग करने के लिए क्लंकी हो सकता है (विशेषकर XOR / दो तरफा सेट अंतर ऑपरेशन की कमी को देखते हुए)।
इसे आम तौर पर ईएवी (इकाई-विशेषता-मूल्य) के रूप में जाना जाता है। मैं खुद प्रशंसक नहीं हूं, लेकिन कभी-कभी इसकी जगह होती है। सिवाय इसके कि आप इसका उपयोग value
के बिना कर रहे होंगे घटक।
आप एक टेबल बनाते हैं:
CREATE TABLE item_attributes (
item_id integer references items(id),
attribute_name text,
primary key(item_id, attribute_name)
);
और प्रत्येक आइटम के लिए एक सरणी-मूल्यवान कॉलम होने के बजाय, प्रत्येक आइटम के लिए प्रत्येक सेट प्रविष्टि के लिए एक पंक्ति डालें। प्राथमिक कुंजी द्वारा लागू की गई अनूठी बाधा यह सुनिश्चित करती है कि किसी भी आइटम में किसी दिए गए विशेषता के डुप्लिकेट नहीं हो सकते हैं। विशेषता क्रम अप्रासंगिक/अपरिभाषित है।
SQL सेट ऑपरेटरों जैसे EXCEPT
. के साथ तुलना की जा सकती है , या array_agg(attribute_name ORDER BY attribute_name)
का उपयोग कर रहे हैं तुलना के लिए लगातार क्रमबद्ध सरणी बनाने के लिए।
अनुक्रमण यह निर्धारित करने तक सीमित है कि किसी दिए गए आइटम में दी गई विशेषता है या नहीं।
व्यक्तिगत रूप से मैं इस दृष्टिकोण पर सरणियों का उपयोग करूँगा।
hstore
आप सेट को स्टोर करने के लिए खाली मानों वाले hstores का भी उपयोग कर सकते हैं, क्योंकि hstore डी-डुप्लिकेट कुंजी। 9.4 का jsonb
इसके लिए भी काम करेगा।
regress=# create extension hstore;
CREATE EXTENSION
regress=# SELECT hstore('a => 1, b => 1') = hstore('b => 1, a => 1, b => 1');
?column?
----------
t
(1 row)
हालांकि, यह केवल टेक्स्ट प्रकारों के लिए वास्तव में उपयोगी है। उदा.:
regress=# SELECT hstore('"1.0" => 1, "2.0" => 1') = hstore('"1.00" => 1, "1.000" => 1, "2.0" => 1');
?column?
----------
f
(1 row)
और मुझे लगता है कि यह बदसूरत है। तो फिर, मैं सरणियों के पक्ष में हूँ।
केवल पूर्णांक सरणियों के लिए
intarray
एक्सटेंशन सरणियों को सेट के रूप में मानने के लिए उपयोगी, तेज़ कार्य प्रदान करता है। वे केवल पूर्णांक सरणियों के लिए उपलब्ध हैं लेकिन वे वास्तव में उपयोगी हैं।