0

次のようなデータベース テーブルがあります (無関係なフィールドを削除しました)。

[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 を使用しました)。

!!!!!!!!!!!!!!!!答え!!!!!!!!!!!!!!

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 と新しい識別子でパーティション化することで、会話をグループ化できます。

4

0 に答える 0