SELECT id, string_agg(year_range, ', ') AS year_ranges
FROM (
SELECT id, CASE WHEN count(*) > 1
THEN min(year)::text || '-' || max(year)::text
ELSE min(year)::text
END AS year_range
FROM (
SELECT *, row_number() OVER (ORDER BY id, year) - year AS grp
FROM (
SELECT id, unnest(years) AS year
FROM (VALUES (2::int, '{1999,2000,2010,2011,2012}'::int[])
,(3, '{1990,1991,2007}')
) AS tbl(id, years)
) sub1
) sub2
GROUP BY id, grp
ORDER BY id, min(year)
) sub3
GROUP BY id
ORDER BY id
उत्पादन करता है बिल्कुल वांछित परिणाम।
यदि आप वर्चर की एक सरणी से निपटते हैं (varchar[]
, बस इसे int[]
. पर डालें , आगे बढ़ने से पहले। ऐसा लगता है कि यह पूरी तरह से कानूनी रूप में है:
years::int[]
आंतरिक उप-चयन को उत्पादक कोड में अपनी स्रोत तालिका के नाम से बदलें।
FROM (VALUES (2::int, '{1999,2000,2010,2011,2012}'::int[])
,(3, '{1990,1991,2007}')
) AS tbl(id, years)
->
FROM tbl
चूंकि हम स्वाभाविक रूप से आरोही संख्या . के साथ काम कर रहे हैं (वर्ष) हम लगातार वर्षों के समूह बनाने के लिए एक शॉर्टकट का उपयोग कर सकते हैं (एक सीमा बनाते हुए)। मैं पंक्ति संख्या से ही वर्ष घटाता हूं (वर्ष के अनुसार क्रमित)। लगातार वर्षों तक, पंक्ति संख्या और वर्ष दोनों में एक की वृद्धि होती है और एक ही grp
उत्पन्न होता है संख्या। वरना, एक नई रेंज शुरू होती है।
विंडो फ़ंक्शंस के बारे में अधिक जानकारी मैनुअल में यहां और यहां ।
इस मामले में एक plpgsql फ़ंक्शन और भी तेज़ हो सकता है। आपको परीक्षण करना होगा। इन संबंधित उत्तरों में उदाहरण:
लगातार दोहराव/डुप्लीकेट की संख्या का आदेश दिया
ROW_NUMBER() अनपेक्षित मान दिखाता हैए>