split_part()
trả về chuỗi trống (''
) - không phải NULL
- khi phần được trả về trống hoặc không tồn tại. Đó là lý do tại sao COALESCE
không có gì nơi đây. Và chuỗi trống (''
) không có đại diện là integer
giá trị, do đó nó tạo ra một lỗi khi cố gắng truyền nó.
Cách ngắn nhất trong ví dụ này phải là GREATEST(split_part( ... ) , '0')
trước khi truyền, vì chuỗi trống sắp xếp trước bất kỳ chuỗi nào khác hoặc thậm chí là NULL (ở bất kỳ ngôn ngữ nào). Sau đó sử dụng DISTINCT ON ()
để nhận hàng có version
"lớn nhất" cho mỗi id
.
Thiết lập thử nghiệm
CREATE TABLE tbl (
id integer NOT NULL
, version text NOT NULL
);
INSERT INTO tbl VALUES
(10, '10-2')
, (10, '10-1')
, (10, '10') -- missing subversion
, (10, '10-111') -- multi-digit number
, (11, '11-1')
, (11, '11-0') -- proper '0'
, (11, '11-') -- missing subversion but trailing '-'
, (11, '11-2');
Giải pháp
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;
Kết quả:
id | version
----+---------
10 | 10-111
11 | 10-2
Hoặc bạn có thể cũng sử dụng NULLIF
và sử dụng NULLS LAST
(theo thứ tự giảm dần) để sắp xếp:
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
Kết quả tương tự.
Hoặc CASE
rõ ràng hơn tuyên bố:
CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle tại đây
Có liên quan:
- Đặt hàng chuỗi varchar dưới dạng số
- Chọn trước hàng trong mỗi GROUP BY nhóm?
- Sắp xếp PostgreSQL theo ngày giờ asc, null trước?
- Cách thực hiện chuyển đổi trống thành rỗng trong PostgreSQL?