SQL Server 2008 R2のデータをフォローする必要があります。 SQLFiddle
スキーマ:
CREATE TABLE [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、 CONSTRAINT [PK_ICFilters] PRIMARY KEY CLUSTERED ([ICFilterID] ASC)WITH 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) 値 (0、 '製品タイプ'、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)
テーブル:
| ICFILTERID | PARENTID | FILTERDESC |アクティブ| ------------------------------------------- ------- | 1 | 0 |製品タイプ| 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 |
すべての行には、親のIDとルートのparentid = 0
。 FilterDesc
sは単なるサンプルの説明なので、順序付けのためにそれらを解析することはできません。
ツリーのような方法ですべての行を選択することは可能ですか?もしそうなら、どうですか? 「ツリーのような」と言うときは、再帰的に親を選択し、その後にすべての子を選択してから、それぞれのすべての子を選択することを意味します。深さ最初のツリートラバーサル。
私の友達と私は試しましたが、実用的な解決策には達していませんが、引き続き試します。私はSQLをかなり初めて使用しているので、これは簡単に行うことができ、必要以上に困難にしています。
例(望ましい)出力:
| ICFILTERID | PARENTID | FILTERDESC |アクティブ| ------------------------------------------- ------- | 1 | 0 |製品タイプ| 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、十分な脳細胞が死んでいます。
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];
上記は私には正しく動作しないようです。 facebookタイプのデータを含む2つのテーブルのセットアップを想像してください。表1には、PostIdと他のフィールドがあります。 PostIdは自動インクリメントであり、明らかにインターフェースでは、DESCをソートして最新の投稿を一番上に配置します。
次に、コメントテーブルについて説明します。表2このテーブルCommentIdは、自動番号である主キーです。あなたのGUIでは、ASCを表示したいので、スレッドを読み取るときに意味がわかります。 (一番上にある最も古い(小さい番号))表2の他の重要なキーは、PostId(投稿へのFK)およびParentId(コメントへのFK)です。これは、これが投稿の「ルート」コメントである場合、ParentIdはNULLになります。誰かがコメントに返信すると、parentIdにcommentidが入力されます。
皆さん、ドリフトをお願いします。 CTEは次のようになります。
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
出力例
1 NULL 0x0000000000000001 0
5 1 0x00000000000000010000000000000001 1
6 5 0x000000000000000100000000000000010000000000000005 2
2 NULL 0x0000000000000002 0
F/B投稿105には、2つのコメント(CommentIds 1および2)があり、誰かがComment1(CommentId 5、ParentId 1)に返信し、他の誰かがその返信にコメントしたため、Comment5(CommentId 6、ParentId 6)
そしてビオラ、シーケンスは正しいです。投稿の下で、正しいシーケンスでコメントを表示できます。 Facebookのように形成して輪郭を描くように投稿をインデントするには(レベルが深くなるほど、左から余白を増やす必要があります)、インデントという列もあります。ルートは0で、ユニオンにはc.Indent + 1 AS Indentがあります。コードでは、インデントを掛けて、32pxを想定し、コメントをニース階層とアウトラインで表示できます。
自動インクリメントの主キーCommentIdをSortKeyを構築する原動力として使用しても問題はありません。+ 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
これにより、すべての子孫とレベルが提供されます。
お役に立てれば :)