Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Escrevendo uma consulta de herança escrita em SQL usando uma junção interna?


Se você estiver olhando para uma hierarquia de árvore, então o modelo de conjunto aninhado funciona muito bem, mas envolve uma grande mudança na estrutura de sua tabela de herança.

Se você estiver implementando um gráfico direcionado arbitrário (por exemplo, você tem um perfil de "autor" que pode publicar artigos, mas não moderar comentários, e um perfil de "moderador" que pode moderar comentários, mas não publicar artigos), convém procurar para alguma outra solução.

Uma possibilidade é desistir da herança e definir manualmente as permissões para cada grupo.

Outra possibilidade é usar a tabela de herança para armazenar herança direta e indireta (ou seja, um nó seria relacionado a todos os seus filhos usando um relacionamento "direto", bem como a todos os seus descendentes usando um relacionamento "indireto"). Esta estratégia requer que você recrie todos os relacionamentos indiretos na tabela sempre que você alterar um dos relacionamentos diretos (isso pode ser feito usando um simples INSERT SELECT ), mas tem a vantagem de exigir apenas uma única junção para acessar todos os descendentes.

A ideia básica é:
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 = ?

O loop na distância deve ser feito até que não haja mais elementos de distância D-1 disponíveis, o que pode ser feito usando uma consulta select ou, se houver, meta-informação sobre quantas linhas foram inseridas.