Créer un index unique :
CREATE UNIQUE INDEX matches_uni_idx ON matches
(greatest(winner, loser), least(winner, loser));
Ne peut pas être un UNIQUE
ou PRIMARY KEY
contrainte, car celles-ci ne fonctionnent qu'avec des colonnes, pas des expressions.
Vous pouvez ajouter un serial
colonne pour servir de PK, mais avec seulement deux colonnes d'entiers, votre PK d'origine est également très efficace (voir les commentaires). Et cela rend les deux colonnes NOT NULL
automatiquement. (Sinon, ajoutez NOT NULL
contraintes.)
Vous pouvez également ajouter un CHECK
contrainte pour exclure les joueurs jouant contre eux-mêmes :
CHECK (winner <> loser)
Astuce :Pour rechercher une paire d'ID (où vous ne savez pas qui a gagné), créez les mêmes expressions dans votre requête, et l'index sera utilisé :
SELECT * FROM matches
WHERE greatest(winner, loser) = 3 -- the greater value, obviously
AND least(winner, loser) = 1;
Si vous traitez des paramètres inconnus et que vous ne savez pas à l'avance lequel est le plus élevé :
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);
Le wrapper CTE est juste pour faciliter la saisie des paramètres une seule fois et n'est pas nécessaire dans certains contextes.