Mysql
 sql >> Base de données >  >> RDS >> Mysql

Écrire une requête d'héritage écrite en SQL à l'aide d'une jointure interne ?

Si vous envisagez une hiérarchie arborescente, le modèle d'ensemble imbriqué fonctionne assez bien, mais implique un changement majeur dans la structure de votre table d'héritage.

Si vous implémentez un graphe orienté arbitraire (par exemple, vous avez un profil "auteur" qui peut publier des articles mais pas modérer les commentaires, et un profil "modérateur" qui peut modérer les commentaires mais pas publier des articles), vous voudrez peut-être regarder pour une autre solution.

Une possibilité consiste à renoncer à l'héritage et à définir manuellement les autorisations pour chaque groupe.

Une autre possibilité consiste à utiliser la table d'héritage pour stocker à la fois l'héritage direct et indirect (c'est-à-dire qu'un nœud serait lié à tous ses enfants en utilisant une relation "directe", ainsi qu'à tous ses descendants en utilisant une relation "indirecte"). Cette stratégie vous oblige à recréer toutes les relations indirectes dans la table chaque fois que vous modifiez l'une des relations directes (cela peut être fait en utilisant un simple INSERT SELECT ), mais présente l'avantage de ne nécessiter qu'une seule jointure pour accéder à tous les descendants.

L'idée de base est :

CREATE TABLE group_inherit (
  parent INT NOT NULL, 
  child INT NOT NULL, 
  distance INT NOT NULL, 
  PRIMARY KEY (parent,child)
);

/* Clean up indirect relations */
DELETE FROM group_inherit WHERE distance <> 0;

/* Repeat this for each D > 0 until the maximum distance is reached */
INSERT IGNORE INTO (parent, child, distance) 
SELECT fst.parent, snd.child, D
FROM group_inherit fst
INNER JOIN group_inherit snd ON snd.parent = fst.child
WHERE fst.distance = 0 AND snd.distance = D - 1;

/* Select all permissions for a user type */
SELECT perm.*
FROM group_permissions perm
INNER JOIN group_inherit ON perm.moderator = child
WHERE parent = ?

La boucle sur la distance doit être effectuée jusqu'à ce qu'il n'y ait plus d'éléments de distance D-1 disponibles, ce qui peut être fait à l'aide d'une requête de sélection ou, si vous en avez, des méta-informations sur le nombre de lignes insérées.