Как создать рекурсивный счетчик с общим выражением таблицы (CTE)? - PullRequest
1 голос
/ 27 декабря 2011

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

Так что тариф у меня есть:

;WITH Reaction(Cnt, ParentId) AS 
(
    SELECT  COUNT(*), ParentId
    FROM   dbo.Post
    GROUP  BY ParentId
)

SELECT ISNULL(Cnt, 0), Post.*
FROM   dbo.Post Post
       LEFT JOIN Reaction
         ON Reaction.ParentId = Post.PostId 

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

Ответы [ 2 ]

2 голосов
/ 27 декабря 2011
  • Сначала создайте список сообщений
  • Совокупность позже
  • Не нужно LEFT JOIN в рекурсивном предложении
  • Необходимо получить ParentID в рекурсивном предложении для следующего уровня, в противном случае вы просто зацикливаете PostId на PostID на том же уровне

Примерно так:

;WITH Reaction AS 
(
    SELECT ParentId
    FROM dbo.Post
    UNION ALL 
    SELECT P.ParentId
    FROM dbo.Post P JOIN Reaction R ON R.ParentId = P.PostId
)
SELECT COUNT(*), ParentId FROM Reaction GROUP BY ParentId;

Редактировать, обновляется с помощью встроенного счетчика

;WITH Reaction AS
(
   SELECT ParentId FROM dbo.Post 
   UNION ALL 
   SELECT P.ParentId FROM dbo.Post P JOIN Reaction R ON R.ParentId = P.PostId
)
SELECT 
     COUNT(*) OVER (PARTITION BY Reactions.ParentId) AS Cnt,
     * 
FROM Post LEFT JOIN Reaction ON Reaction.ParentId = Post.PostId
0 голосов
/ 27 декабря 2011

В итоге я использовал двойной CTE для подсчета (на основании ответа @gbn).Мне это нужно, потому что у меня было поле XML, которое нужно было перечислить , поэтому я не мог использовать GROUP BY.

;WITH Reaction AS 
(
    SELECT ParentId
    FROM dbo.Post
    WHERE ParentId IS NOT NULL
    UNION ALL 
    SELECT P.ParentId
    FROM dbo.Post P JOIN Reaction R ON R.ParentId = P.PostId
    WHERE P.ParentId IS NOT NULL
), 
Reactions AS
(
    SELECT COUNT(*) as CNT, ParentId 
    FROM Reaction 
    GROUP BY ParentId
)

SELECT ISNULL(Reactions.CNT, 0), * 
FROM Post LEFT JOIN Reactions 
    ON Reactions.ParentId = Post.PostId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...