Създайте уникален индекс:
CREATE UNIQUE INDEX matches_uni_idx ON matches
(greatest(winner, loser), least(winner, loser));
Не може да бъде UNIQUE
или PRIMARY KEY
ограничение, тъй като те работят само с колони, а не с изрази.
Можете да добавите serial
колона, за да служи като PK, но само с две целочислени колони, вашият оригинален PK също е много ефективен (вижте коментарите). И прави двете колони NOT NULL
автоматично. (В противен случай добавете NOT NULL
ограничения.)
Можете също да добавите CHECK
ограничение за изключване на играчи, които играят срещу себе си:
CHECK (winner <> loser)
Съвет:За да търсите двойка идентификатори (където не знаете кой спечели), вградете същите изрази във вашата заявка и индексът ще се използва:
SELECT * FROM matches
WHERE greatest(winner, loser) = 3 -- the greater value, obviously
AND least(winner, loser) = 1;
Ако работите с неизвестни параметри и не знаете кое е по-голямо предварително:
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);
CTE обвивката е само за удобство да въвеждате параметри само веднъж и не е необходима в някои контексти.