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