Về cơ bản, truy vấn của bạn không chính xác để bắt đầu. Sử dụng UNION ALL
, không phải hoặc bạn sẽ loại bỏ các mục trùng lặp không chính xác. (Không có gì để nói rằng đường mòn không thể chuyển đổi qua lại giữa các email giống nhau.) UNION
Việc triển khai Postgres cho UNION ALL
trả về các giá trị trong chuỗi dưới dạng được thêm vào - miễn là bạn không thêm ORDER BY
ở cuối hoặc làm bất kỳ điều gì khác với kết quả.
Tuy nhiên, hãy lưu ý rằng mỗi SELECT
trả về các hàng theo thứ tự tùy ý trừ khi ORDER BY
được thêm vào. Không có thứ tự tự nhiên trong các bảng.
Tương tự là không đúng cho UNION
, phải xử lý tất cả các hàng để loại bỏ các bản sao có thể có. Có nhiều cách khác nhau để xác định các bản sao, thứ tự kết quả của các hàng phụ thuộc vào thuật toán đã chọn và phụ thuộc vào việc triển khai và hoàn toàn không đáng tin cậy - trừ khi, một lần nữa, ORDER BY
được thêm vào.
Vì vậy, hãy sử dụng thay thế:
SELECT * FROM iter1
UNION ALL -- union all!
SELECT * FROM iter2;
Để có được một thứ tự sắp xếp đáng tin cậy và "mô phỏng bản ghi tăng trưởng", bạn có thể theo dõi các cấp như sau:
WITH RECURSIVE all_emails AS (
SELECT *, 1 AS lvl
FROM audit_trail
WHERE old_email = '[email protected]'
UNION ALL -- union all!
SELECT t.*, a.lvl + 1
FROM all_emails a
JOIN audit_trail t ON t.old_email = a.new_email
)
TABLE all_emails
ORDER BY lvl;
db <> fiddle tại đây
sqlfiddle
cũ
Bên cạnh:if old_email
không được xác định UNIQUE
theo một cách nào đó, bạn có thể nhận được nhiều đường mòn. Bạn sẽ cần một cột duy nhất (hoặc kết hợp các cột) để giữ cho nó rõ ràng. Nếu vẫn thất bại, bạn có thể (ab-) sử dụng tuple ID nội bộ ctid
với mục đích phân biệt các con đường mòn. Nhưng bạn nên sử dụng các cột của riêng mình. (Đã thêm ví dụ trong fiddle.)
Cân nhắc: