SELECT MS(列)和DISTINCT由MS SQL中的两列之一

时间:2016-05-09 09:19:19

标签: sql sql-server sql-server-2008 sql-server-2014

使用MS SQL Server 2014.我需要选择其中(userid = 1或memberid = 1)的行,其中来自用户#1发送或接收的所有消息的max(messageid)值由messageid desc排序

我在这里尝试了解决方案:How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?,但由于用户可以发送或接收消息,解决方案只能部分解决我的问题。

消息表

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

2 个答案:

答案 0 :(得分:3)

这似乎可以完成这项工作 - 如果您使用分区函数,则非常简单:

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表达式来导出PARTITION值,基本上是"在WHERE子句"中没有匹配的列。 。扩展到两列以上可能比较棘手。

答案 1 :(得分:1)

 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