Je dois suivre les données dans SQL Server 2008 R2. SQLFiddle
Schéma:
CRÉER UN TABLEAU [dbo]. [ICFilters] ( [ICFilterID] [int] IDENTITY (1,1) NOT NULL, [ParentID] [int] NOT NULL DEFAULT 0 , [FilterDesc] [varchar] (50) NOT NULL, [Active] [tinyint] NOT NULL DEFAULT 1, CONTRAINT [PK_ICFilters] PRIMARY KEY CLUSTERED ([ICFilterID] ASC) AVEC PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY] INSERT INTO [dbo]. [ICFilters] (ParentID, FilterDesc, Active) Valeurs (0, 'Product Type', 1), (1, 'ProdSubType_1', 1), (1, 'ProdSubType_2', 1), (1, 'ProdSubType_3', 1), (1, 'ProdSubType_4', 1), (2, 'PST_1.1', 1), (2, 'PST_1.2', 1), (2, 'PST_1.3', 1), (2, 'PST_1.4', 1), (2, 'PST_1.5', 1), (2, 'PST_1.6', 1), (2, 'PST_1.7', 0), (3, 'PST_2.1', 1), (3, 'PST_2.2', 0), [._ ___.] (3, 'PST_2.3', 1), (3, 'PST_2.4', 1), (14, 'PST_2.2.1', 1), (14, 'PST_2.2.2', 1), (14, 'PST_2.2.3', 1), (3, 'PST_2.8', 1)
Table:
| ICFILTERID | PARENTID | FILTERDESC | ACTIF | ------------------------------------------- ------- | 1 | 0 | Type de produit | 1 | | 2 | 1 | ProdSubType_1 | 1 | | 3 | 1 | ProdSubType_2 | 1 | | 4 | 1 | ProdSubType_3 | 1 | | 5 | 1 | ProdSubType_4 | 1 | | 6 | 2 | PST_1.1 | 1 | | 7 | 2 | PST_1.2 | 1 | | 8 | 2 | PST_1.3 | 1 | | 9 | 2 | PST_1.4 | 1 | | 10 | 2 | PST_1.5 | 1 | | 11 | 2 | PST_1.6 | 1 | | 12 | 2 | PST_1.7 | 0 | | 13 | 3 | PST_2.1 | 1 | | 14 | 3 | PST_2.2 | 0 | | 15 | 3 | PST_2.3 | 1 | | 16 | 3 | PST_2.4 | 1 | | 17 | 14 | PST_2.2.1 | 1 | | 18 | 14 | PST_2.2.2 | 1 | | 19 | 14 | PST_2.2.3 | 1 | | 20 | 3 | PST_2.8 | 1 |
Chaque ligne a l'ID de son parent et le parentid = 0
. Les FilterDesc
ne sont que des exemples de descriptions, donc je ne peux pas essayer de les analyser pour les commander.
Est-il possible de sélectionner toutes les lignes de manière arborescente? Si c'est le cas, comment? Quand je dis "en forme d'arbre", je veux dire sélectionner récursivement le parent suivi par tous ses enfants, puis tous les enfants de chacun d'entre eux et ainsi de suite. Une première traversée d'arbre en profondeur.
Mes amis et moi avons essayé, mais nous n'avons pas réussi à trouver des solutions de travail, mais nous continuerons d'essayer. Je suis assez nouveau dans sql, donc cela peut être fait facilement et je rends les choses plus difficiles que nécessaire.
Exemple de sortie (souhaitée):
| ICFILTERID | PARENTID | FILTERDESC | ACTIF | ------------------------------------------- ------- | 1 | 0 | Type de produit | 1 | | 2 | 1 | ProdSubType_1 | 1 | | 6 | 2 | PST_1.1 | 1 | | 7 | 2 | PST_1.2 | 1 | | 8 | 2 | PST_1.3 | 1 | | 9 | 2 | PST_1.4 | 1 | | 10 | 2 | PST_1.5 | 1 | | 11 | 2 | PST_1.6 | 1 | | 12 | 2 | PST_1.7 | 0 | | 3 | 1 | ProdSubType_2 | 1 | | 13 | 3 | PST_2.1 | 1 | | 14 | 3 | PST_2.2 | 0 | | 17 | 14 | PST_2.2.1 | 1 | | 18 | 14 | PST_2.2.2 | 1 | | 19 | 14 | PST_2.2.3 | 1 | | 15 | 3 | PST_2.3 | 1 | | 16 | 3 | PST_2.4 | 1 | | 20 | 3 | PST_2.8 | 1 | | 4 | 1 | ProdSubType_3 | 1 | | 5 | 1 | ProdSubType_4 | 1 |
OK, assez de cellules cérébrales sont mortes.
WITH cte AS
(
SELECT
[ICFilterID],
[ParentID],
[FilterDesc],
[Active],
CAST(0 AS varbinary(max)) AS Level
FROM [dbo].[ICFilters]
WHERE [ParentID] = 0
UNION ALL
SELECT
i.[ICFilterID],
i.[ParentID],
i.[FilterDesc],
i.[Active],
Level + CAST(i.[ICFilterID] AS varbinary(max)) AS Level
FROM [dbo].[ICFilters] i
INNER JOIN cte c
ON c.[ICFilterID] = i.[ParentID]
)
SELECT
[ICFilterID],
[ParentID],
[FilterDesc],
[Active]
FROM cte
ORDER BY [Level];
Ce qui précède ne semble pas fonctionner correctement pour moi. Imaginez une configuration à 2 tables avec des données de type facebook. Le tableau 1, a PostId + vous d'autres champs. PostId est incrémenté automatiquement et, évidemment, dans votre interface, vous trierez DESC pour avoir le dernier message en haut.
Maintenant, pour le tableau des commentaires. Tableau 2 Ce tableau CommentId est la clé primaire, numéro automatique. Dans votre interface graphique, vous souhaitez l'afficher en ASC, de sorte que lors de la lecture du fil, cela ait du sens. (le plus ancien (nombre le plus petit) en haut) Les autres clés importantes du tableau 2 sont: PostId (FK retour aux publications) et ParentId (FK à CommentId) où ParentId sera NULL s'il s'agit du commentaire "racine" sur une publication. Si quelqu'un RÉPOND à un commentaire, alors le parentId sera rempli avec le commentid.
J'espère que vous aurez compris. Le CTE ressemblera à ceci:
WITH Comments
AS ( SELECT CommentId , ParentId, CAST(CommentId AS VARBINARY(MAX)) AS Sortkey, 0 AS Indent
FROM dbo.Comments
WHERE ParentId IS NULL AND PostId = 105
UNION ALL
SELECT b.CommentId , b.ParentId, c.Sortkey + CAST(b.CommentId AS varbinary(max)) AS Sortkey, c.Indent + 1 AS Indent
FROM dbo.Comments b
INNER JOIN Comments c ON c.CommentId = b.ParentId
)
SELECT *
FROM Comments
ORDER BY Sortkey
Exemple de sortie
1 NULL 0x0000000000000001 0
5 1 0x00000000000000010000000000000001 1
6 5 0x000000000000000100000000000000010000000000000005 2
2 NULL 0x0000000000000002 0
Sur F/B post 105, il y avait deux commentaires (CommentIds 1 et 2) Quelqu'un a ensuite répondu sur Comment1 (CommentId 5, ParentId 1), puis quelqu'un d'autre a commenté cette réponse, ainsi de suite Comment5 (CommentId 6, ParentId 6)
Et l'alto, la séquence est correcte, sous le post, vous pouvez maintenant afficher les commentaires dans la bonne séquence. Pour mettre en retrait les messages afin qu'ils se forment et se dessinent comme dans Facebook (plus le niveau est profond, plus il doit être margé à partir de la gauche), j'ai également une colonne appelée Retrait. Les racines sont 0, puis dans l'union, nous avons c.Indent + 1 AS Indent Dans le code, vous pouvez maintenant multiplier le retrait avec laisse supposer 32px, et afficher les commentaires dans une hiérarchie et un contour Nice.
Je ne vois aucun problème à utiliser la clé primaire d'incrémentation automatique CommentId comme force motrice pour la création de ma SortKey, car il y a un meilleur changement de vous gâcher les dates (date de commentaire) que de gâcher une clé gérée par la base de données qui contient +1
create table pc ( parent varchar(10), child varchar(10) )
insert into pc values('a','b');
insert into pc values('a','c');
insert into pc values('b','e');
insert into pc values('b','f');
insert into pc values('a','d');
Insert into pc values('b','g');
insert into pc values('c','h');
insert into pc values('c','i');
insert into pc values('d','j');
insert into pc values('f','k');
insert into pc values('x','y');
insert into pc values('y','z');
insert into pc values('m','n');
DECLARE @parent varchar(10) = 'a';
WITH cte AS
(
select null parent, @parent child, 0 as level
union
SELECT a.parent, a.child , 1 as level
FROM pc a
WHERE a.parent = @parent
UNION ALL
SELECT a.parent, a.child , c.level + 1
FROM pc a JOIN cte c ON a.parent = c.child
)
SELECT distinct parent, child , level
FROM cte
order by level, parent
Cela vous donnera tous les descendants et le niveau.
J'espère que cela t'aides :)