复杂查询中的SQL Server中的GROUP BY

时间:2015-02-16 10:52:44

标签: sql-server

我需要按T.TopicID对此进行分组才能收到最后的结果。

无论我尝试什么,我都会得到错误,就像其他T.项目咆哮包括在分组或聚合等

ALTER PROCEDURE [dbo].[SPGetFollowingTopics]
    @id int = null
    ,@UserGroupId int = null
    ,@lastvisit DateTime = null
AS
    SELECT *
    FROM
       (SELECT
           ROW_NUMBER() OVER (ORDER BY TopicOrder DESC,
                                    (CASE 
                                        WHEN M.MessageCreationDate > T.TopicCreationDate 
                                          THEN M.MessageCreationDate
                                          ELSE T.TopicCreationDate
                                      END) DESC) AS RowNumber, 
           T.TopicId, T.TopicTitle, T.TopicShortName,  
           T.TopicDescription, T.TopicCreationDate, T.TopicViews, 
           T.TopicReplies, T.UserId, T.TopicTags, T.TopicIsClose, 
           T.TopicOrder, T.LastMessageId, U.UserName, 
           M.MessageCreationDate, T.ReadAccessGroupId, 
           T.PostAccessGroupId, TF.userid AS Expr1, U.UserGroupId, 
           U.UserPhoto, U.UserFullName, M.UserId AS MessageUserId,
           MU.UserName AS MessageUserName
        FROM            
           Topics AS T 
        LEFT OUTER JOIN
           Messages AS M ON M.TopicId = T.TopicId AND M.Active = 1 AND M.MessageCreationDate < @lastvisit
        INNER JOIN 
           topicfollows AS TF ON T.TopicId = TF.topicid    
        INNER JOIN
           Users AS U ON U.UserId = T.UserId
        LEFT JOIN 
           Users MU ON MU.UserId = M.UserId
        WHERE
           (TF.userid = @id) 
       ) T

2 个答案:

答案 0 :(得分:1)

目前尚不清楚要求是什么(在我看来),但我认为你正在寻求:

  1. “最新消息”
  2. PER TOPIC
  3. 给定用户
  4. 在这种情况下,ROW_NUMBER()是一个不错的选择,但我相信你需要对ROW_NUMBER进行PARTITION以及订购它。

    SELECT
          *
    FROM (
          SELECT
                ROW_NUMBER() OVER (PARTITION BY TF.userid, T.TopicId 
                                   ORDER BY
                                        (CASE
                                              WHEN M.MessageCreationDate > T.TopicCreationDate THEN M.MessageCreationDate
                                              ELSE T.TopicCreationDate
                                        END) DESC) AS ROWNUMBER
              , T.TopicId, T.TopicTitle, T.TopicShortName, T.TopicDescription
              , T.TopicCreationDate, T.TopicViews, T.TopicReplies, T.UserId
              , T.TopicTags, T.TopicIsClose, T.TopicOrder, T.LastMessageId
              , U.UserName, M.MessageCreationDate, T.ReadAccessGroupId
              , T.PostAccessGroupId, TF.userid AS EXPR1
              , U.UserGroupId, U.UserPhoto, U.UserFullName
              , M.UserId AS MESSAGEUSERID, MU.UserName AS MESSAGEUSERNAME
          FROM Topics AS T
          LEFT OUTER JOIN Messages AS M ON M.TopicId = T.TopicId
                      AND M.Active = 1
                      AND M.MessageCreationDate < @lastvisit
          INNER JOIN topicfollows AS TF ON T.TopicId = TF.topicid
          INNER JOIN Users AS U ON U.UserId = T.UserId
          LEFT JOIN Users MU ON MU.UserId = M.UserId
          WHERE (TF.userid = @id)
    ) T
    WHERE ROWNUMBER = 1
    

答案 1 :(得分:0)

您可以将左连接更改为任意outer apply,然后添加TOP 1

SELECT ...
FROM            
    Topics AS T 
OUTER APPLY
(   SELECT  TOP 1 M.MessageCreationDate, M.UserId
    FROM    Messages AS M 
    WHERE   M.TopicId = T.TopicId 
    AND     M.Active = 1 
    AND     M.MessageCreationDate < @lastvisit
    ORDER BY M.MessageCreationDate DESC
) AS m

这允许您使用TOP 1,并且每topicID

仍然可以获得一行

或者,您可以使用ROW_NUMBER() OVER(PARTITION BY m.TopicID ORDER BY M.MessageCreationDate DESC)

SELECT ...
FROM            
    Topics AS T 
LEFT OUTER JOIN
(   SELECT  M.TopicId,
            M.MessageCreationDate, 
            M.UserId, 
            RowNum = ROW_NUMBER() OVER(PARTITION BY m.TopicID ORDER BY M.MessageCreationDate DESC)
    FROM    Messages AS M 
    WHERE   M.Active = 1
    AND     M.MessageCreationDate < @lastvisit
) AS m
    ON M.TopicId = T.TopicId 
    AND m.RowNum = 1

我会测试这两种方法,看看哪种方法最适合你。