Giải pháp
Để tìm nút có nhiều nút con nhất:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... và loại trừ các nút gốc:
SELECT *
FROM (
SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
) ct
LEFT JOIN (
SELECT tbl_id
FROM tbl
WHERE path = ''
) x USING (tbl_id)
WHERE x.tbl_id IS NULL
ORDER BY children DESC
LIMIT 1
Giả sử rằng các nút gốc có ltree
trống (''
) dưới dạng đường dẫn. Có thể là NULL
. Sau đó sử dụng path IS NULL
...
Người chiến thắng trong ví dụ của bạn thực sự là 2001
, với 5 người con.
Làm thế nào?
-
Sử dụng hàm
subpath(...)
được cung cấp bởi mô-đun bổ sungltree
. -
Nhận nút cuối cùng trong đường dẫn có độ lệch âm , là cha trực tiếp của phần tử.
-
Đếm tần suất xuất hiện của nút gốc đó, loại trừ các nút gốc và lấy nút còn lại có số lượng cao nhất.
-
Sử dụng
ltree2text()
để trích xuất giá trị từltree
. -
Nếu nhiều nút có hầu hết các nút con bằng nhau, một nút tùy ý sẽ được chọn trong ví dụ.
Trường hợp thử nghiệm
Đây là công việc tôi phải làm để có được một trường hợp thử nghiệm hữu ích (sau khi loại bỏ một số nhiễu):
Xem SQLfiddle .
Nói cách khác:hãy nhớ cung cấp một trường hợp thử nghiệm hữu ích vào lần sau.
Các cột bổ sung
Trả lời để nhận xét.
Đầu tiên, hãy mở rộng trường hợp thử nghiệm:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Hãy xem:
SELECT * FROM tbl;
Chỉ cần JOIN
kết quả đến cấp độ gốc trong bảng cơ sở:
SELECT ct.*, t.postal_code
FROM (
SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
) ct
LEFT JOIN (
SELECT tbl_id
FROM tbl
WHERE path = ''
) x USING (tbl_id)
JOIN tbl t USING (tbl_id)
WHERE x.tbl_id IS NULL
ORDER BY children DESC
LIMIT 1;