Buat indeks unik:
CREATE UNIQUE INDEX matches_uni_idx ON matches
(greatest(winner, loser), least(winner, loser));
Tidak boleh UNIQUE atau PRIMARY KEY kendala, karena itu hanya bekerja dengan kolom, bukan ekspresi.
Anda dapat menambahkan serial kolom untuk berfungsi sebagai PK, tetapi hanya dengan dua kolom bilangan bulat, PK asli Anda juga sangat efisien (lihat komentar). Dan itu membuat kedua kolom NOT NULL secara otomatis. (Jika tidak, tambahkan NOT NULL kendala.)
Anda juga dapat menambahkan CHECK batasan untuk mengesampingkan pemain yang bermain melawan diri mereka sendiri:
CHECK (winner <> loser)
Petunjuk:Untuk mencari sepasang ID (di mana Anda tidak tahu siapa yang menang), buat ekspresi yang sama ke dalam kueri Anda, dan indeks akan digunakan:
SELECT * FROM matches
WHERE greatest(winner, loser) = 3 -- the greater value, obviously
AND least(winner, loser) = 1;
Jika Anda berurusan dengan parameter yang tidak diketahui dan Anda tidak tahu mana yang lebih baik sebelumnya:
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);
Pembungkus CTE hanya untuk kemudahan memasukkan parameter sekali saja dan tidak diperlukan dalam beberapa konteks.