9.4 या बाद के पोस्टग्रेट्स
WITH ORDINALITY
सेट-रिटर्न फ़ंक्शंस के लिए उपयोग करें :
जब FROM
क्लॉज में एक फ़ंक्शन द्वारा प्रत्यय लगाया जाता है WITH ORDINALITY
, तो एक
bigint
कॉलम आउटपुट के लिए जोड़ा जाता है जो 1 से शुरू होता है और फ़ंक्शन के आउटपुट की प्रत्येक पंक्ति के लिए 1 से इंक्रीमेंट होता है। यह सेट रिटर्निंग फंक्शन्स जैसे कि के मामले में सबसे उपयोगी है unnest()
।
LATERAL
Pgql -hackers पर pg 9.3l और इस थ्रेड के अनुसार फीचर के साथ संयोजन में , उपरोक्त क्वेरी अब इस प्रकार लिखी जा सकती है:
SELECT t.id, a.elem, a.nr
FROM tbl AS t
LEFT JOIN LATERAL unnest(string_to_array(t.elements, ','))
WITH ORDINALITY AS a(elem, nr) ON TRUE;
LEFT JOIN ... ON TRUE
बाईं तालिका में सभी पंक्तियों को सुरक्षित रखता है, भले ही तालिका अभिव्यक्ति दाईं ओर कोई पंक्तियां न लौटाए। यदि आपको कोई चिंता नहीं है तो आप इसे अन्यथा समतुल्य, कम क्रियात्मक रूप में निहित के साथ उपयोग कर सकते हैं CROSS JOIN LATERAL
:
SELECT t.id, a.elem, a.nr
FROM tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr);
या सरल अगर एक वास्तविक सरणी ( arr
एक सरणी स्तंभ होने के नाते) आधारित है:
SELECT t.id, a.elem, a.nr
FROM tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr);
या न्यूनतम सिंटैक्स के साथ भी:
SELECT id, a, ordinality
FROM tbl, unnest(arr) WITH ORDINALITY a;
a
स्वचालित रूप से तालिका और स्तंभ उपनाम है। अतिरिक्त क्रमबद्धता कॉलम का डिफ़ॉल्ट नाम है ordinality
। लेकिन स्पष्ट स्तंभ उपनाम और तालिका-योग्य कॉलम जोड़ने के लिए यह बेहतर (सुरक्षित, क्लीनर) है।
Postgres 8.4 - 9.3
आपके साथ row_number() OVER (PARTITION BY id ORDER BY elem)
क्रमबद्ध क्रम के अनुसार संख्याएँ मिलती हैं, न कि मूल क्रमिक स्थिति की क्रमिक संख्या कि स्ट्रिंग में ।
आप बस छोड़ सकते हैं ORDER BY
:
SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t;
हालांकि यह सामान्य रूप से काम करता है और मैंने इसे कभी भी सरल प्रश्नों में विफल नहीं देखा, पोस्टग्रेसीएल बिना पंक्तियों के आदेश के बारे में कुछ भी नहीं कहता है ORDER BY
। यह एक कार्यान्वयन विवरण के कारण काम करने के लिए होता है।
रिक्त-पृथक स्ट्रिंग में तत्वों की क्रमिक संख्या की गारंटी के लिए :
SELECT id, arr[nr] AS elem, nr
FROM (
SELECT *, generate_subscripts(arr, 1) AS nr
FROM (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
) sub;
या सरल अगर एक वास्तविक सरणी के आधार पर :
SELECT id, arr[nr] AS elem, nr
FROM (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t;
संबंधित उत्तर dba.SE पर:
पोस्टग्रेज 8.1 - 8.4
इन सुविधाओं में से कोई भी अभी तक उपलब्ध हैं,: RETURNS TABLE
, generate_subscripts()
, unnest()
, array_length()
। लेकिन यह काम करता है:
CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
RETURNS SETOF record
LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1
FROM generate_series(array_lower($1,1), array_upper($1,1)) i';
विशेष रूप से ध्यान दें, कि सरणी सूचकांक तत्वों के क्रमिक पदों से भिन्न हो सकता है। एक विस्तारित फ़ंक्शन के साथ इस डेमो पर विचार करें :
CREATE FUNCTION f_unnest_ord_idx(anyarray, OUT val anyelement, OUT ordinality int, OUT idx int)
RETURNS SETOF record
LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1, i
FROM generate_series(array_lower($1,1), array_upper($1,1)) i';
SELECT id, arr, (rec).*
FROM (
SELECT *, f_unnest_ord_idx(arr) AS rec
FROM (VALUES (1, '{a,b,c}'::text[])
, (2, '[5:7]={a,b,c}')
, (3, '[-9:-7]={a,b,c}')
) t(id, arr)
) sub;
id | arr | val | ordinality | idx
1 | {a,b,c} | a | 1 | 1
1 | {a,b,c} | b | 2 | 2
1 | {a,b,c} | c | 3 | 3
2 | [5:7]={a,b,c} | a | 1 | 5
2 | [5:7]={a,b,c} | b | 2 | 6
2 | [5:7]={a,b,c} | c | 3 | 7
3 | [-9:-7]={a,b,c} | a | 1 | -9
3 | [-9:-7]={a,b,c} | b | 2 | -8
3 | [-9:-7]={a,b,c} | c | 3 | -7
की तुलना करें: