web-dev-qa-db-fra.com

Construire une boîte de trois table avec une table récursive au milieu?

J'ai trois tables pertinentes: Pièces, PartGroup et Markupgroup.

Les pièces sont simples.

PartID          artificial primary key
Part            part number
PartGroupID     Foreign key

exemple de données:

1   T1000           5
2   wizbang gold    17
3   flux capacitor  2

PartGroup est un graphique acyclique dirigé (arbre) modelé avec une clé parent autocollante

PartGroupID     artificial primary key
Description     name of group
ParentID        foreign key linked to PartGroupID
MarkupGroupID   foreign key linked to MarkupGroup

Les échantillons de données ressembleraient à cela-

1   system      null    null
2   component   null    1 
3   software    null    2
4   abc         1       3
5   xyz         1       4
6   123         4       null
7   456         4       null
8   789         5       null
9   a1          6       null
10  b2          6       null
11  c3          7       null
12  d4          7       null
13  e5          8       null  
14  f6          8       null
15  alpha       3       null
16  beta        3       null
17  gamma       3       null

Markupgroup consiste à appliquer un facteur de balisage à plusieurs groupes de partitions en tant que jeu.

MarkupGroupID   primary key
MarkupFactor    numeric attribute field

exemple de données-

1   15
2   20
3   25
4   22

Je dois écrire une requête qui retourne le montant de balisage approprié pour chaque partie de la table des pièces. Il n'y a jamais de cas lorsque plus d'un marquillage peut s'appliquer à une partie. Je dois recueillir le graphique pour trouver le balisage et je ne saurai pas au moment de la requête combien de niveaux je dois recueillir pour trouver un balisage non nul.

Il n'y a jamais eu de cas lorsqu'une pièce rencontrera plus d'une jointure possible à une marge sur la gravité de l'arbre, il n'ya donc aucun accumulation qui doit être fait.

Le T1000 est de type XYZ, qui a une clé étrangère pour un groupe de margue, afin que nous puissions rejoindre et obtenir une valeur. Il a aussi un parent, mais cela n'est pas pertinent car nous avons la valeur dont nous avons besoin.

WIZBANG GOLD est un logiciel de groupe gamma, qui n'a pas de clé étrangère, mais le "logiciel" du nœud parent et nous devrions le retourner.

Un condensateur de flux est un composant, et il a une clé étrangère directe à un marggroup. Retourne cette valeur.

Les résultats seraient donc:

1   T1000           22
2   wizbang gold    20
3   flux capacitor  15

Je suis sûr que je vais avoir besoin d'une CTE récursive et de la saveur de postuler pour l'obtenir, mais mon cerveau ne fonctionne pas très bien pour le moment. Sinon, pour la nature récursive du tableau du milieu, ce serait assez simple. La plate-forme est MS-SQL.

5
Jeff Sacksteder

Vous pouvez faire la récursivité dans un CTE de la descente du haut vers le bas MarkupGroupID avec vous.

with C as
(
  select P.PartGroupID,
         P.ParentID,
         P.MarkupGroupID
  from PartGroup as P
  where P.ParentID is null
  union all 
  select P.PartGroupID,
         P.ParentID,
         coalesce(P.MarkupGroupID, C.MarkupGroupID)
  from PartGroup as P 
    inner join C 
      on P.ParentID = C.PartGroupID
)
select P.PartID,
       P.Part,
       MG.MarkupFactor
from Parts as P
  inner join C
    on P.PartGroupID = C.PartGroupID
  inner join MarkupGroup as MG
    on C.MarkupGroupID = MG.MarkupGroupID
order by P.PartID

SQL FIDDLE

Le CTE récursif va créer une table dérivée qui ressemble à ceci.

PartGroupID ParentID    MarkupGroupID
----------- ----------- -------------
1           NULL        NULL
2           NULL        1
3           NULL        2
15          3           2
16          3           2
17          3           2
4           1           3
5           1           4
8           5           4
13          8           4
14          8           4
6           4           3
7           4           3
11          7           3
12          7           3
9           6           3
10          6           3

Si vous avez besoin de pièces avec PartGroup non connecté à un marquage, vous pouvez utiliser une jointure externe contre MarkupGroup dans votre requête principale.

with C as
(
  select ...
)
select P.PartID,
       P.Part,
       MG.MarkupFactor
from Parts as P
  inner join C
    on P.PartGroupID = C.PartGroupID
  left outer join MarkupGroup as MG
    on C.MarkupGroupID = MG.MarkupGroupID
order by P.PartID
5
Mikael Eriksson