2011-11-27 2 views
3

저는 꽤 일반적인 블로그 방식으로 기사에 대한 의견을 검색하려고했습니다. 나는 이런 식으로 작업 할 수있는 CTE 쿼리를 사용할 수 있다고 생각댓글 들여 쓰기가있는 부모 - 자식 쿼리

-- ---------------------------- 
-- Sample Table structure for [dbo].[Comments] 
-- ---------------------------- 
CREATE TABLE [dbo].[Comments] (
[CommentID] int NOT NULL , 
[AddedDate] datetime NOT NULL , 
[AddedBy] nvarchar(256) NOT NULL , 
[ArticleID] int NOT NULL , 
[Body] nvarchar(4000) NOT NULL , 
[parentCommentID] int NULL 
) 


GO 

-- ---------------------------- 
-- Sample Records of Comments 
-- ---------------------------- 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body],  [parentCommentID]) VALUES (N'1', N'2011-11-26 23:18:07.000', N'user', N'1', N'body', null); 
GO 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body], [parentCommentID]) VALUES (N'2', N'2011-11-26 23:18:50.000', N'user', N'2', N'body', null); 
GO 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body], [parentCommentID]) VALUES (N'3', N'2011-11-26 23:19:09.000', N'user', N'1', N'body', null); 
GO 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body], [parentCommentID]) VALUES (N'4', N'2011-11-26 23:19:46.000', N'user', N'3', N'body', null); 
GO 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body], [parentCommentID]) VALUES (N'5', N'2011-11-26 23:20:16.000', N'user', N'1', N'body', N'1'); 
GO 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body], [parentCommentID]) VALUES (N'6', N'2011-11-26 23:20:42.000', N'user', N'1', N'body', N'1'); 
GO 
INSERT INTO [dbo].[Comments] ([CommentID], [AddedDate], [AddedBy], [ArticleID], [Body], [parentCommentID]) VALUES (N'7', N'2011-11-26 23:21:25.000', N'user', N'1', N'body', N'6'); 
GO 

-- ---------------------------- 
-- Indexes structure for table Comments 
-- ---------------------------- 

-- ---------------------------- 
-- Primary Key structure for table [dbo].[Comments] 
-- ---------------------------- 
ALTER TABLE [dbo].[Comments] ADD PRIMARY KEY ([CommentID]) 
GO 

-- ---------------------------- 
-- Foreign Key structure for table [dbo].[Comments] 
-- ---------------------------- 
ALTER TABLE [dbo].[Comments] ADD FOREIGN KEY ([parentCommentID]) REFERENCES [dbo]. [Comments] ([CommentID]) ON DELETE NO ACTION ON UPDATE NO ACTION 
GO 

: 여기 내 예제 코드의

WITH CommentsCTE(CommentID, AddedDate, AddedBy, ArticleID, Body, parentCommentID, lvl, sortcol) 
AS 
(
SELECT CommentID, AddedDate, AddedBy, ArticleID, Body, parentCommentID, 0, cast(CommentID as varbinary(max)) 
FROM Comments 
UNION ALL 
SELECT P.CommentID, P.AddedDate, P.AddedBy, P.ArticleID, P.Body, P.parentCommentID, PP.lvl+1, 
CAST(sortcol + CAST(P.CommentID AS BINARY(4)) AS VARBINARY(max)) 
FROM Comments AS P 
JOIN CommentsCTE AS PP 
ON P.parentCommentID = PP.CommentID 
) 
SELECT 
REPLICATE('--', lvl) 
+ right('>',lvl)+ AddedBy 
+ ' :: ' 
+ Body, 
CommentID, 
parentCommentID, 
lvl 
FROM CommentsCTE 
WHERE ArticleID = 1 
order by sortcol 
go 

을하지만 결과는 지금까지 매우 실망했고, 조정 I의 일 후에 도움을 청하기로 결심했다. 블로그에서 일어나는 것처럼 기사에 계층 적 주석을 표시하는 방법을 찾고있었습니다.

[편집] [편집][편집]이 쿼리의 문제점은 표시 할 의견을 원하는 ArticleID를 올바르게 선택하는 방법을 찾지 못해 중복 된 것을 얻을 수 있다는 것입니다. 나 또한 같은 수준 내에서 날짜별로 어린이 항목을 정렬하는 방법을 찾고 있습니다. 뭔가처럼 될 수 달성하기 위해 노력하고있어의 예 : 나는 좀 자신이 모든 혼란에 열중하고 있었다

(ArticleID[post retrieved]) 
------------------------- 
------------------------- 
(Comments[related to the article id above]) 
first comment[no parent] 
--[first child to first comment] 
--[second child to first comment] 
----[first child to second child comment to first comment] 
--[third child to first comment] 
----[first child to third child comment to first comment] 
------[(recursive child): first child to first child to third child comment to first comment] 
------[(recursive child): second child to first child to third child comment to first comment] 
second comment[no parent] 
third comment[no parent] 
--[first child to third comment] 

... 난 어떤 도움이나이 작업을 얻을 수있는 간단한 방법을 주셔서 감사합니다. 감사합니다.

+0

어떻게 실망합니까? 현재의 결과는 당신이 찾고자했던 것과 어떻게 다른가요? – Bert

+0

글쎄, 그 쿼리에서 나는 거기에 있지 않았던 복제본을 얻었고 적절한 방식으로 날짜별로 주석을 정렬하는 방법을 알 수 없었다. – poldoj

답변

4

매우 가까이에 있습니다. 앵커 쿼리에 중복

where parentCommentID is null 

을 제거 추가

WITH CommentsCTE (CommentID, AddedDate, AddedBy, ArticleID, Body, parentCommentID, lvl, Thread) 
AS 
(
    SELECT CommentID, 
      AddedDate, 
      AddedBy, 
      ArticleID, 
      Body, 
      parentCommentID, 
      0, 
      ROW_NUMBER() over (order by CommentID) as Thread 
    FROM @Comments 
    where parentCommentID is null 

    UNION ALL 

    SELECT P.CommentID, 
      P.AddedDate, 
      P.AddedBy, 
      P.ArticleID, 
      P.Body, 
      P.parentCommentID,  
      PP.lvl+1, 
      PP.Thread 
    FROM @Comments AS P 
    JOIN CommentsCTE AS PP ON P.parentCommentID = PP.CommentID 
) 
SELECT REPLICATE('--', lvl) + right('>',lvl)+ AddedBy + ' :: ' + Body, 
     CommentID, 
     parentCommentID, 
     lvl, 
     AddedDate, 
     Thread 
FROM CommentsCTE 
WHERE ArticleID = 1 
order by Thread, CommentID 

첫째 : 당신의 재귀 쿼리에 두 개의 수정을했습니다. 둘째, 제대로 정렬하려면 Thread 식별자가 필요합니다. 앵커 쿼리에 행 번호를 추가하여 스레드 번호를 만들었습니다. 이를 통해 결과를 적절히 정렬 할 수 있습니다.

Here is an example of it in action.

+0

많은, 많은 많은 감사드립니다. 정확히 내가 찾고 있었던 것 같습니다. 그것은 광범위하게 테스트 될 것이고 앞으로 더 많은 피드백을보고 할 것입니다. – poldoj