6
votes

Déplacement de la table de fermeture avec plusieurs parents

J'ai le DAG suivant

DELETE FROM `Closure`
WHERE `Descendant` IN (SELECT `Descendant` FROM `Closure` WHERE `Ancestor`=@Node)
AND `Ancestor` NOT IN (SELECT `Descendant` FROM `Closure` WHERE `Ancestor`=@Node);


0 commentaires

4 Réponses :


1
votes

En langage naturel, ce serait: "Supprimer les relicotions descendantes de l'ancêtre à D, s'il n'y a pas de parent de D en plus de B qui est également un descendant d'un". Est-ce correct?

( éditer: em> non, ce n'est pas correct; non seulement des relicotions à D doivent être supprimées, mais aussi des relicotions à chaque descendant de D forte>. Ainsi, que les critères ne sont pas valides ...) p>

mon SQL provisoire serait alors: p> xxx pré>

(désolé si j'ai eu la mauvaise requête - ou utilisé non - Caractéristiques standard - Je ne suis pas réellement expérimenté avec ça. Mais ma description de la langue naturelle devrait donner une idée de ce qui doit réellement aller sur la requête) p>


Mise à jour: forte > À la deuxième pensée, je ne crois pas que ma requête fonctionnera pour tous les cas. Considérez ceci: p>

A --> B --> D --> E --> F


0 commentaires

2
votes

Tout d'abord, je crois qu'il y a une entrée en double dans votre table. (a, d) code> apparaît deux fois. Deuxièmement, après avoir retiré le bord (b, d) code>, les chemins suivants doivent rester:

  1. nœud auto-cartes: (a, a) code>, (B, B) code>, (c, c) code>, (D, D) CODE> LI>
  2. (a, b) code> li>
  3. (a, c) code> li>
  4. (a, d) code> (via c) li> ol>

    Ainsi, pour retirer le bord (b, d) code> Dans cet exemple, tout ce qui est nécessaire est de supprimer celui-ci: P>

    Delete MyTable 
    Where Ancestor = 'B'
        And Descendant = 'D'
    


3 commentaires

Le duplicata (A, D) est en réalité la racine de cette question - il existe pour montrer que dans une table de fermeture, vous en auriez un (A, D) causé par ABD et un de l'ACD. Comment détecter-je quand un autre chemin coupe-ps dans ce diamant et non supprimé (A, D)? De préférence uniquement en utilisant SQL et uniquement le bord (B, D).


@NTSCCOBALT - Il n'a aucun sens d'avoir (a, d) là-bas deux fois. Une table de fermeture ne décrit pas comment un nœud se connecte avec un autre; seulement que un nœud se connecte avec un autre. Ainsi, si (a, d) est dans la table, il n'a pas d'importance si le chemin d'accès à partir de a à d était < Code> A> B> C> E> .....> x> y> d ou a> d . C'est le but. Le tableau de fermeture vous évite de devoir calculer ce chemin à chaque fois. Si vous essayez de capturer les chemins utilisés pour obtenir un nœud à un autre, une table de fermeture n'est pas la solution. Planifiez plutôt le graphique dans une table des bords et calculez le chemin.


Ah, oui, j'ai du mal à me souvenir pourquoi j'ai demandé à cette question d'être honnête. Je ne me souviens pas vraiment de ce que nous avons décidé de faire en solution. Je pense que l'intention initiale était de comprendre un moyen de supprimer le bord de (B, D) et de supprimer toutes les entrées dans la table de fermeture causée par elle sans retirer accidentellement les bords qui existent toujours. La seule solution que je puisse penser immédiatement à reconstruire la totalité de la table de fermeture des nœuds que vous savez ne sont que 1 à pas.



3
votes

Compte tenu de votre modèle actuel, je ne suis pas sûr que ce soit possible. Je proposerais que vous ajoutez une colonne pour compter le nombre de chemins suivis du nombre de manières différentes à partir de tout nœud x au noeud y .

Plutôt que votre table, vous vous retrouvez avec xxx

supprimer un nœud impliquerait alors une instruction de mise à jour suivie d'une instruction DELETE. La mise à jour aurait, au lieu de supprimer les entrées qu'il trouve, décrémentez le nombre de références pour cette entrée. Ensuite, vous pouvez supprimer les entrées avec 0 ou moins de références par la suite.

À venir avec une requête SQL qui me fait échapper à la mise à jour pour le moment, mais en théorie, cela devrait fonctionner sans avoir à reconstruire complètement la table de fermeture ...


1 commentaires

Approche intéressante. Je me demande si plusieurs références d'ancêtre à descendre pourraient avoir des profondeurs différentes, comment mettrez-vous à jour la profondeur si l'un des REF est supprimé?



0
votes

Tout en suivant la profondeur et permettant à plusieurs parents en même temps est probablement possible, je reçois une odeur de code de celui-ci, surtout lorsque la solution implique d'avoir des deux couples. Thomas 'Réponse des contours qui émettent .

Je vais simplifier la question un peu pour vous concentrer sur Disvertir un nœud lorsque plusieurs parents sont autorisés forts>, car c'est un problème assez délicat. Je jette entièrement la colonne de profondeur et en supposant qu'il n'y a pas de paires en double. P>

Vous devez prendre en compte les enfants de D, ce qui est compliqué rapidement. Disons que nous avons: p> xxx pré>

Nous voulons dissimuler d de b, ce qui signifie que nous devons également supprimer les liens entre E et B. mais si elles sont connectées comme ceci: p> xxx pré>

Dans ce cas si nous déconnectons b> d, nous ne voulons plus non plus, car e est toujours lié à B à C. mais nous faisons Voulez-vous déconnecter F de b. P>

Je vais passer par ma solution ci-dessous en utilisant ce deuxième exemple. Je sais que D n'a qu'un parent dans cet exemple, mais cela fonctionne toujours parfaitement si D a plusieurs parents; Je peux plus facilement démontrer certains des cas de bord de cette façon, c'est pourquoi je le fais comme ça. P>

Voici ce que la table ressemblerait à: p> xxx pré>

Query 1: Obtenez tous les descendants de D, y compris d strud> p> xxx pré>

Ceci retournera: d, e, f Code> p>

Query 2: Obtenez tous les ancêtres de B, y compris B STRY> P>

A --> B --> C
             
            |
            v

      D --> E < -- G
      
      |
      V

H --> F


0 commentaires