Développeurs SQL, j'ai pour tâche d'en apprendre beaucoup sur SQL Server 2012 sur une base de données mal planifiée.
SO, il y a la table Elem
:
+-----------+----+---+----------+------------+
|VERSION(PK)|NAME|KEY|PARENT_KEY|DIST_KEY(FK)|
+-----------+----+---+----------+------------+
|1 |a |12 |NULL |1 |
+-----------+----+---+----------+------------+
|2 |b |13 |12 |1 |
+-----------+----+---+----------+------------+
|3 |c |14 |13 |1 |
+-----------+----+---+----------+------------+
|4 |d |15 |12 |1 |
+-----------+----+---+----------+------------+
|5 |e |16 |NULL |1 |
+-----------+----+---+----------+------------+
|6 |e |17 |NULL |2 |
+-----------+----+---+----------+------------+
Après la mise à jour de la ligne, je dois vérifier la clé parent de l’élément afin de ne pas autoriser cet élément à être autogéré ou quelque chose du genre.
Et lorsque je supprime la ligne, je dois supprimer tous les enfants et les enfants d’enfants, etc.
Les questions sont:
Comment puis-je sélectionner tous les "parents + grands-parents + etc" d'un élément de DIST?
Comment puis-je sélectionner tous les "fils + petits-fils + etc" d'un élément de DIST?
J'ai lu des articles sur les solutions avec CTE, mais je n'ai aucune racine d'éléments et je ne comprends même pas comment utiliser CTE à ce moment-là.
S'il vous plaît, aidez!
Merci.
J'ai rencontré ce problème , J'ai résolu le problème de cette façon
--all "parent + grandparent + etc" @childID Replaced with the ID you need
with tbParent as
(
select * from Elem where [KEY]=@childID
union all
select Elem.* from Elem join tbParent on Elem.[KEY]=tbParent.PARENT_KEY
)
SELECT * FROM tbParent
--all "sons + grandsons + etc" @parentID Replaced with the ID you need
with tbsons as
(
select * from Elem where [KEY]=@parentID
union all
select Elem.* from Elem join tbsons on Elem.PARENT_KEY=tbsons.[KEY]
)
SELECT * FROM tbsons
PS.Mon anglais n'est pas bon.
voici une requête récursive vous donnant tous les ancêtres et tous les descendants d'un élément. Utilisez-les ensemble ou séparez-les en fonction de la situation. Remplacez les clauses where pour obtenir l'enregistrement souhaité. Dans cet exemple, je cherche la clé 13 (il s’agit de l’élément portant le nom = b) et trouve son ancêtre 12/a et son descendant 14/c.
with all_ancestors(relation, version, name, elem_key, parent_key, dist_key)
as
(
-- the record itself
select 'self ' as relation, self.version, self.name, self.elem_key, self.parent_key, self.dist_key
from elem self
where elem_key = 13
union all
-- all its ancestors found recursively
select 'ancestor ' as relation, parent.version, parent.name, parent.elem_key, parent.parent_key, parent.dist_key
from elem parent
join all_ancestors child on parent.elem_key = child.parent_key
)
, all_descendants(relation, version, name, elem_key, parent_key, dist_key)
as
(
-- the record itself
select 'self ' as relation, self.version, self.name, self.elem_key, self.parent_key, self.dist_key
from elem self
where elem_key = 13
union all
-- all its descendants found recursively
select 'descendant' as relation, child.version, child.name, child.elem_key, child.parent_key, child.dist_key
from elem child
join all_descendants parent on parent.elem_key = child.parent_key
)
select * from all_ancestors
union
select * from all_descendants
order by elem_key
;
Voici le violon SQL: http://sqlfiddle.com/#!6/617ee/28 .
J'ai créé une fonction permettant de rechercher les parents d'un enfant spécifique où vous devez passer l'identifiant de l'enfant.
Ceci retournera la liste des parents sous forme de chaîne séparée par des virgules ..__ Essayez ceci si cela fonctionne pour vous.
Je suppose que le parent_key with null value
est la racine.
CREATE FUNCTION checkParent(@childId INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @parentId VARCHAR(MAX) = NULL
DECLARE @parentKey INT = null
SET @parentId = (SELECT parent_key FROM Elem WHERE [KEY] = @childId)
WHILE(@parentKey IS NOT NULL)
begin
SET @parentId = @parentId + ', ' + (SELECT parent_key FROM Elem WHERE [KEY] = @parentId)
SET @parentKey = (SELECT parent_key FROM Elem WHERE [KEY] = @parentId)
END
RETURN @parentId
END
GO
Je ne pense pas que cela puisse être fait d’une seule manière dans tous les cas, de sorte que vous puissiez sélectionner tous les parents, grands-parents, .... Une façon de le faire est de joindre elem table à elle-même, et cela dépend du nombre de niveaux de jointure que vous faites, du niveau de vos enfants, de vos petits-enfants que vous obtiendrez.
La solution peut être quelque chose comme ça (pour le deuxième cas)
cela vous sélectionnera tous les parents, enfants et petits-enfants
Select
parent.key as parent_key,
child.key as child_key,
grandchild.key as grandchild_key
from elem parent
join elem child on (elem.key=child.parentkey)
join elem grandchild on (child.key=grandchild.parentkey)
where parent.parentkey is null; -- this make you sure that first level will be parents
la solution pour le premier cas est simplement que vous allez connecter des tables non pas dans le style 'clé = clé =' mais opposées 'parentkey = clé'.