如何更有效地编写此查询?

时间:2011-04-16 16:51:33

标签: sql-server performance

在我的个人资料网站上,用户可以发表评论,评论评论(像facebook这样的1级)。我正在实施一些分页,因为在1个配置文件中可能有数千条评论。分页有效,但是,由于存在子注释,因此简单的顶部 n 查询会中断对话。我只想对父评论进行分页,而不是孩子。

表'评论' 它有:

- commentID
- commentText
- parentCommentID
- commentOnUserID

这里的问题是我只想对父项的注释(parentCommentID = 0)进行分页。所以我写了一个像这样的查询:

select * from Comments c
where c.parentCommentID = 0 
and c.commentOnUserID = 65939 

(我遗漏了实际的分页查询,因为它不相关)

但我也想加载所有这些评论的孩子,一个孩子也是一个评论,但随后用parentCommentID = some commentID:

select * from comments c
where c.parentCommentID in ( * get the commentId's from the previous query)
and c.commentOnUserID = 65939

有没有办法有效地结合二合一查询?

3 个答案:

答案 0 :(得分:2)

declare @T table(commentID int,
                 commentText varchar(max),
                 parentCommentID int,
                 commentOnUserID int)

insert into @T values
(1, 'Comment 1', 0, 1),
(2, 'Comment 2', 0, 1),
(3, 'Comment 3', 0, 1),
(4, 'Comment 4 sub 1', 1, 1),
(5, 'Comment 5 sub 1', 1, 1),
(6, 'Comment 6 sub 1', 1, 1),
(7, 'Comment 1 sub 2', 2, 1),
(8, 'Comment 1 sub 2', 2, 1),
(9, 'Comment 1 sub 3', 3, 1)

declare @UserID int = 1

;with cte as
(
  select
    T.commentID,
    T.CommentText,
    row_number() over(order by commentID) as rn
  from @T as T
  where
    T.parentCommentID = 0 and
    T.commentOnUserID = @UserID
  union all
  select   
    T.commentID,
    T.CommentText,
    C.rn
  from @T as T
    inner join cte as C
      on T.parentCommentID = C.commentID
)
select *
from cte
where rn between 1 and 2 -- use rn for pagination
order by rn, commentID

结果

commentID   parentCommentID CommentText          rn
----------- --------------- -------------------- --------------------
1           0               Comment 1            1
4           1               Comment 4 sub 1      1
5           1               Comment 5 sub 1      1
6           1               Comment 6 sub 1      1
2           0               Comment 2            2
7           2               Comment 1 sub 2      2
8           2               Comment 1 sub 2      2

答案 1 :(得分:1)

这样的事情:

WITH
    ParentComment AS (
        SELECT * from Comments c
        WHERE c.parentCommentID = 0 
        AND c.commentOnUserID = 65939 
    )
SELECT * 
FROM Comments c
WHERE c.commentOnUserID = 65939
AND (
    c.CommentID IN (SELECT CommentID FROM ParentComment)
    OR c.ParentCommentID IN (SELECT CommentID FROM ParentComment)
)

尚未测试SQL Server中的语法,但这应该是一般的想法。

答案 2 :(得分:0)

我会用以下方式做到这一点:

SELECT p.*, c.* 
FROM comment c LEFT JOIN comment p ON (c.parentCommentID = p.commentID)
WHERE p.parentCommentID = 0
AND p.commentOnUserID = 65939

我确信有一些方法可以很好地将父级包含在子级结果中,但我知道在MySQL中至少存在在连接条件下放置OR的性能问题。