在MS SQL中选择MAX(列)和DISTINCT by两列中的一列

在MS SQL中选择MAX(列)和DISTINCT by两列中的一列,sql,sql-server,sql-server-2008,sql-server-2014,Sql,Sql Server,Sql Server 2008,Sql Server 2014,使用MS SQL Server 2014。我需要选择userid=1或memberid=1的行,该行在用户1发送或接收messageid desc排序的所有消息中具有maxmessageid值 我在这里尝试了解决方案:,但由于用户可以发送或接收消息,该解决方案只能部分解决我的问题 消息表 messageid userid memberid message created -----------------------------------------------------------

使用MS SQL Server 2014。我需要选择userid=1或memberid=1的行,该行在用户1发送或接收messageid desc排序的所有消息中具有maxmessageid值

我在这里尝试了解决方案:,但由于用户可以发送或接收消息,该解决方案只能部分解决我的问题

消息表

messageid  userid  memberid  message  created
--------------------------------------------------------------
9          4       1         Hi 9     2016-05-09 01:50:59.423 
8          4       1         Hi 8     2016-05-09 01:50:43.950
7          1       4         Hi 7     2016-05-09 01:50:35.310
6          1       4         Hi 6     2016-05-09 01:50:25.887
5          1       2         Hi 5     2016-05-08 23:49:41.610
11         2       1         Hi 11    2016-05-09 03:26:42.267
12         1       3         Hi 12    2016-05-09 05:06:11.030
1          1       2         Hi 1     2016-05-08 22:37:57.803
预期结果

messageid  userid  memberid  message  created
--------------------------------------------------------------
12         1       3         Hi 12    2016-05-09 05:06:11.030
11         2       1         Hi 11    2016-05-09 03:26:42.267
9          4       1         Hi 9     2016-05-09 01:50:59.423 
我试过了

DECLARE @userid bigint

SET @userid=1

SELECT mm.*
FROM messages mm
INNER JOIN
    (SELECT memberid AS otherperson, MAX(m.messageid) AS MaxID
    FROM messages m
    WHERE m.userid=@userid
    GROUP BY memberid   
    ) groupedmm 
ON mm.memberid = groupedmm.otherperson 
AND mm.messageid = groupedmm.MaxID

UNION

SELECT mmm.*
FROM messages mmm
INNER JOIN
    (SELECT userid AS otherperson, MAX(m.messageid) AS MaxID
    FROM messages m
    WHERE m.memberid=@userid
    GROUP BY userid 
    ) groupedmmm 
ON mmm.userid = groupedmmm.otherperson 
AND mmm.messageid = groupedmmm.MaxID
以上查询已返回

messageid  userid  memberid  message  created
--------------------------------------------------------------
5          1       2         Hi 5     2016-05-08 23:49:41.610
7          1       4         Hi 7     2016-05-09 01:50:35.310
9          4       1         Hi 9     2016-05-09 01:50:59.423
11         2       1         Hi 11    2016-05-09 03:26:42.267 
12         1       3         Hi 12    2016-05-09 05:06:11.030

这似乎可以完成任务-如果使用分区函数,则非常简单:

declare @user_id int
set @user_id = 1
declare @t table (messageid tinyint, userid tinyint, memberid tinyint, message varchar(17),
                  created datetime)
insert into @t(messageid,  userid,  memberid,  message,  created) values
(9          ,4       ,1         ,'Hi 9'     ,'2016-05-09T01:50:59.423'),
(8          ,4       ,1         ,'Hi 8'     ,'2016-05-09T01:50:43.950'),
(7          ,1       ,4         ,'Hi 7'     ,'2016-05-09T01:50:35.310'),
(6          ,1       ,4         ,'Hi 6'     ,'2016-05-09T01:50:25.887'),
(5          ,1       ,2         ,'Hi 5'     ,'2016-05-08T23:49:41.610'),
(11         ,2       ,1         ,'Hi 11'    ,'2016-05-09T03:26:42.267'),
(12         ,1       ,3         ,'Hi 12'    ,'2016-05-09T05:06:11.030'),
(1          ,1       ,2         ,'Hi 1'     ,'2016-05-08T22:37:57.803')

;With Ordered as (
    select *,
        ROW_NUMBER() OVER (PARTITION BY
           CASE WHEN userid = @user_id THEN memberid else userid END
           ORDER BY created desc) rn
    from @t
    where
        userid = @user_id or
        memberid = @user_id
)
select * from Ordered where rn = 1
结果:

messageid userid memberid message           created                 rn
--------- ------ -------- ----------------- ----------------------- --------------------
11        2      1        Hi 11             2016-05-09 03:26:42.267 1
12        1      3        Hi 12             2016-05-09 05:06:11.030 1
9         4      1        Hi 9              2016-05-09 01:50:59.423 1

请注意,使用CASE表达式派生分区值,本质上是WHERE子句中不匹配的列。扩展到两列以上可能更为棘手。

因此,输入是一个适当设置的@userid变量,所需的输出是表示最新消息的整行,而不是像您在问题的前面指定/暗示的那样,您说您刚好在最高messageidies之后的最新消息,但是userid=1或memberid=1。嗯,想象一下Facebook上的信息是如何排列的谢谢。您还改进了性能:表“messages”。扫描计数1,逻辑读取3。我在:扫描计数4,逻辑读取12,只完成了一半
 CREATE TABLE #D
(
MESSAGEID INT,  USERID INT, MEMBERID INT,  MESSAGE VARCHAR(10),  CREATED DATETIME)
INSERT INTO #D VALUES


(9,4,1,'HI 9','2016-05-09 01:50:59.423'),
(8,4,1,'HI 8','2016-05-09 01:50:43.950'),
(7,1,4,'HI 7','2016-05-09 01:50:35.310'),
(6,1,4,'HI 6','2016-05-09 01:50:25.887'),
(5,1,2,'HI 5','2016-05-08 23:49:41.610'),
(11,2,1,'HI 11','2016-05-09 03:26:42.267'),
(12,1,3,'HI 12','2016-05-09 05:06:11.030'),
(1,1,2,'HI 1','2016-05-08 22:37:57.803')  



 SELECT TT.*
    FROM #D TT
    INNER JOIN
        (SELECT USERID, MAX(CREATED) AS MAXDATETIME
        FROM #D
        GROUP BY USERID) GROUPEDTT 
    ON TT.USERID = GROUPEDTT.USERID 
    AND TT.CREATED = GROUPEDTT.MAXDATETIME