Crea un indice univoco:
CREATE UNIQUE INDEX matches_uni_idx ON matches
(greatest(winner, loser), least(winner, loser));
Non può essere un UNIQUE
o PRIMARY KEY
vincolo, poiché funzionano solo con le colonne, non con le espressioni.
Potresti aggiungere un serial
colonna per fungere da PK, ma con solo due colonne intere, anche la tua PK originale è molto efficiente (vedi commenti). E rende entrambe le colonne NOT NULL
automaticamente. (Altrimenti, aggiungi NOT NULL
vincoli.)
Potresti anche aggiungere un CHECK
vincolo per escludere i giocatori che giocano contro se stessi:
CHECK (winner <> loser)
Suggerimento:per cercare una coppia di ID (di cui non sai chi ha vinto), inserisci le stesse espressioni nella tua query e verrà utilizzato l'indice:
SELECT * FROM matches
WHERE greatest(winner, loser) = 3 -- the greater value, obviously
AND least(winner, loser) = 1;
Se hai a che fare con parametri sconosciuti e non sai in anticipo quale sia il maggiore:
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);
Il wrapper CTE serve solo per comodità per inserire i parametri una sola volta e non è necessario in alcuni contesti.