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
Sản xuất chính xác kết quả mong muốn.
Nếu bạn xử lý một mảng varchar (varchar[]
, chỉ cần truyền nó tới int[]
, trước khi bạn tiếp tục. Nó có vẻ ở dạng hoàn toàn hợp pháp cho điều đó:
years::int[]
Thay thế lựa chọn phụ bên trong bằng tên của bảng nguồn của bạn trong mã hiệu quả.
FROM (VALUES (2::int, '{1999,2000,2010,2011,2012}'::int[])
,(3, '{1990,1991,2007}')
) AS tbl(id, years)
->
FROM tbl
Vì chúng tôi đang xử lý số tăng dần (năm) chúng ta có thể sử dụng một phím tắt để tạo thành các nhóm các năm liên tiếp (tạo thành một phạm vi). Tôi trừ chính năm đó khỏi số hàng (thứ tự theo năm). Trong các năm liên tiếp, cả số hàng và số năm đều tăng một và tạo ra cùng một grp
con số. Nếu không, một phạm vi mới sẽ bắt đầu.
Thông tin thêm về chức năng cửa sổ trong sách hướng dẫn tại đây và tại đây .
Một hàm plpgsql có thể còn nhanh hơn trong trường hợp này. Bạn sẽ phải kiểm tra. Ví dụ trong các câu trả lời có liên quan sau:
Số lần lặp lại / trùng lặp có thứ tự