Tạo một chỉ mục duy nhất:
CREATE UNIQUE INDEX matches_uni_idx ON matches
(greatest(winner, loser), least(winner, loser));
Không được là UNIQUE
hoặc PRIMARY KEY
ràng buộc, vì chúng chỉ hoạt động với cột chứ không phải biểu thức.
Bạn có thể thêm một serial
để phục vụ như PK, nhưng chỉ với hai cột số nguyên, PK ban đầu của bạn cũng rất hiệu quả (xem nhận xét). Và nó làm cho cả hai cột NOT NULL
tự động. (Nếu không, hãy thêm NOT NULL
ràng buộc.)
Bạn cũng có thể thêm CHECK
ràng buộc để loại trừ người chơi đấu với mình:
CHECK (winner <> loser)
Gợi ý:Để tìm kiếm một cặp ID (mà bạn không biết ai đã thắng), hãy xây dựng các biểu thức giống nhau vào truy vấn của bạn và chỉ mục sẽ được sử dụng:
SELECT * FROM matches
WHERE greatest(winner, loser) = 3 -- the greater value, obviously
AND least(winner, loser) = 1;
Nếu bạn xử lý các thông số không xác định và bạn không biết thông số nào lớn hơn trước thời hạn:
WITH input AS (SELECT $id1 AS _id1, $id2 AS _id2) -- input once
SELECT * FROM matches, input
WHERE greatest(winner, loser) = greatest(_id1, _id2)
AND least(winner, loser) = least(_id1, _id2);
Trình bao bọc CTE chỉ để thuận tiện cho việc nhập các tham số một lần duy nhất và không cần thiết trong một số ngữ cảnh.