我有一个类似于此的数据库表(我删除了不相关的字段)
[dbo].[UserMessage]
(
[OwnerUserId] [int] NOT NULL,
[FromUserId] [int] NOT NULL,
[ToUserId] [int] NOT NULL,
[CreationDateTime] [datetime2](7) NOT NULL
)
在此表中,我有以下数据
OwnerUserId FromUserId ToUserId CreationDateTime
13 13 15 2013-06-26 13:58:01.0270000
15 13 15 2013-06-26 13:58:24.0770000
13 15 13 2013-06-26 14:08:58.0070000
15 15 13 2013-06-26 14:08:43.8570000
13 13 15 2013-06-26 14:09:15.1030000
15 13 15 2013-06-26 14:09:26.2000000
13 15 13 2013-06-26 14:09:47.0030000
15 15 13 2013-06-26 14:09:38.1330000
13 13 16 2013-06-26 14:20:27.5170000
16 13 16 2013-06-26 14:20:41.0130000
我想要的是一个SQL查询,它为不同用户之间的粒子所有者返回最新的不同消息。 所以如果我想要OwnerUserId = 13的所有对话,我希望返回的结果是
OwnerUserId FromUserId ToUserId CreationDateTime
13 13 16 2013-06-26 14:20:27.5170000
13 15 13 2013-06-26 14:09:47.0030000
如果我想要OwnerUserId = 15的所有会话,我希望返回的结果是
OwnerUserId FromUserId ToUserId CreationDateTime
15 15 13 2013-06-26 14:09:38.1330000
如果我想要OwnerUserId = 16的所有会话,我希望返回的结果是
OwnerUserId FromUserId ToUserId CreationDateTime
16 13 16 2013-06-26 14:20:41.0130000
我为[OwnerUserId] = 13
创建了一个类似于此的查询WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY OwnerUserId, fromUserId, ToUserId ORDER BY CreationDateTime DESC) AS rn
FROM [UserMessage]
)
SELECT *
FROM cte
WHERE rn = 1
and [OwnerUserId] = 13;
但此查询返回
OwnerUserId FromUserId ToUserId CreationDateTime rn
13 13 15 2013-06-26 14:09:15.1030000 1
13 13 16 2013-06-26 14:20:27.5170000 1
13 15 13 2013-06-26 14:09:47.0030000 1
我不希望返回顶行,因为最后一行已经代表同一个对话(尽管FromUserID和ToUserId被反转)。 有任何想法吗? 该解决方案适用于任何[OwnerUserId](我使用13作为示例)
!!!!!!!!!!!!!!!! ANSWER !!!!!!!!!!!!!!
WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER
(
PARTITION BY OwnerUserId,
CHECKSUM(CASE WHEN ToUserId > fromUserId THEN (convert(varchar(256),ToUserId) + ':' + convert(varchar(256),fromUserId)) ELSE (convert(varchar(256),fromUserId) + ':' + convert(varchar(256),ToUserId)) END)
ORDER BY CreationDateTime desc
) AS rn
FROM [UserMessage]
)
SELECT *
FROM cte
WHERE rn = 1
and [OwnerUserId] = 13;
我通过在查询分区中使用校验和来达到解决方案。 基本上我将fromUserId和toUserId结合起来为对话创建唯一的标识符。通过对OwnerUserId和新标识符进行分区,我可以将对话组合在一起。