Комментарии Parent-Child запрос с отступом - PullRequest
3 голосов
/ 27 ноября 2011

Я пытался получить комментарии к статьям довольно распространенным способом блога. Вот мой пример кода:

-- ----------------------------
-- 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

Я подумал, что мог бы использовать запрос CTE для выполнения такой работы:

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

но результаты пока очень разочаровывают, и после нескольких дней настройки я решил обратиться за помощью. Я искал способ отображения иерархических комментариев к статьям, как это происходит в блогах.

[править] Проблема с этим запросом состоит в том, что я получаю дубликаты, потому что я не мог понять, как правильно выбрать 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]

Я как бы заблудился во всем этом беспорядке ... Я ценю любую помощь или более простые способы заставить это работать. Спасибо

1 Ответ

4 голосов
/ 27 ноября 2011

Вы были очень близки. Я сделал две модификации вашего рекурсивного запроса:

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

Сначала добавим

where parentCommentID is null

к вашему якорному запросу удаляет ваши дубликаты. Во-вторых, для их правильной сортировки вам необходим идентификатор потока. Я добавил номер строки в ваш запрос привязки, чтобы создать номер потока. Это позволяет правильно сортировать результаты.

Вот пример этого в действии.

...