Utwórz unikalny indeks:
CREATE UNIQUE INDEX matches_uni_idx ON matches
(greatest(winner, loser), least(winner, loser));
Nie może być UNIQUE
lub PRIMARY KEY
ograniczenie, ponieważ działają one tylko z kolumnami, a nie wyrażeniami.
Możesz dodać serial
kolumna, która ma służyć jako PK, ale mając tylko dwie kolumny z liczbami całkowitymi, oryginalny PK jest również bardzo wydajny (patrz komentarze). I sprawia, że obie kolumny są NOT NULL
automatycznie. (W przeciwnym razie dodaj NOT NULL
ograniczenia.)
Możesz również dodać CHECK
ograniczenie, aby wykluczyć graczy grających przeciwko sobie:
CHECK (winner <> loser)
Wskazówka:aby wyszukać parę identyfikatorów (gdzie nie wiesz, kto wygrał), wbuduj te same wyrażenia do zapytania, a zostanie użyty indeks:
SELECT * FROM matches
WHERE greatest(winner, loser) = 3 -- the greater value, obviously
AND least(winner, loser) = 1;
Jeśli masz do czynienia z nieznanymi parametrami i nie wiesz z wyprzedzeniem, który z nich jest większy:
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);
Opakowanie CTE służy tylko do wygodnego wprowadzania parametrów tylko raz i nie jest konieczne w niektórych kontekstach.