2016-02-07 39 views
1

我需要此任務的幫助: 我在MsSql數據庫中有一張表,用於存儲消息間用戶消息。我需要一個查詢來爲每個用戶對話選擇最後一條消息(WhatApp就像用戶的對話列表)。sql查詢通過對話將數據分組

表結構(x是消息ID,GUID,並且是針對每個消息唯一的,txtMsg是文本消息):

| messageId | fromUserId | toUserId | Message |  sentDate  | 
|  x  |  1  |  2 | txtMsg | 1.1.2016 1:00:00 | 
|  x  |  1  |  2 | txtMsg | 1.1.2016 1:00:01 | 
|  x  |  1  |  2 | txtMsg | 1.1.2016 1:00:02 | 
|  x  |  2  |  1 | txtMsg | 1.1.2016 1:00:03 | 
|  x  |  3  |  1 | txtMsg | 1.1.2016 1:00:04 | 
|  x  |  4  |  1 | txtMsg | 1.1.2016 1:00:05 | 
|  x  |  2  |  3 | txtMsg | 1.1.2016 1:00:06 | 
|  x  |  2  |  4 | txtMsg | 1.1.2016 1:00:07 | 
|  x  |  2  |  3 | txtMsg | 1.1.2016 1:00:08 | 
|  x  |  1  |  5 | txtMsg | 1.1.2016 1:00:09 | 
|  x  |  3  |  1 | txtMsg | 1.1.2016 1:00:10 | 
|  x  |  2  |  4 | txtMsg | 1.1.2016 1:00:11 | 
|  x  |  2  |  5 | txtMsg | 1.1.2016 1:00:12 | 
|  x  |  1  |  2 | txtMsg | 1.1.2016 1:00:13 | 

預期結果例如,對於ID爲用戶= 1( sentDate是最新的日期):

|  x  |  1  |  2 | txtMsg | 1.1.2016 1:00:13 | 
|  x  |  3  |  1 | txtMsg | 1.1.2016 1:00:10 | 
|  x  |  4  |  1 | txtMsg | 1.1.2016 1:00:05 | 
|  x  |  1  |  5 | txtMsg | 1.1.2016 1:00:09 | 

什麼sql查詢會創建這樣的結果?

謝謝!

後來編輯: 我加入這裏sqlfiddle例如:

http://sqlfiddle.com/#!3/6ffbe/15

+0

這裏的想法是按固定順序爲'from'和'to'設置ID。例如,您可以使用'CASE WHEN ... END'構建。 –

回答

5

您可以使用row_nubmer以案例的邏輯來獲得的最小和最大的用戶ID:

select m.* 
from (select m.*, 
      row_number() over (partition by (case when fromuserid < touserid then fromuserid else touserid end), 
               (case when fromuserid < touserid then touserid else fromuserid end) 
           order by sentDate desc 
           ) as seqnum 
     from messages m 
    ) m 
where seqnum = 1; 

編輯:

此SQL可用於SQL Fiddle

select m.* 
from (select m.*, 
      row_number() over (partition by (case when fromuser < touser then fromuser else touser end), 
               (case when fromuser < touser then touser else fromuser end) 
           order by createdAt desc 
           ) as seqnum 
     from messages m 
    ) m 
where seqnum = 1; 
+0

我在http://sqlfiddle.com/#!3/6ffbe/15上添加了這個表格 –

+0

我無法讓您的代碼運行。請問,請將查詢放在我的sqlfiddle表上? –

+0

現在運作。謝謝。 –

1

如何沿着

SELECT * FROM MessageData 
WHERE messageID in 
    (SELECT messageID FROM 
    SELECT Max(sentDate), Max(messageID) messageID FROM 
     MessageData m1 
     INNER JOIN 
     MessageData m2 
     ON 
     m1.fromUserId = m2.toUserId 
     OR 
     m2.fromUserId = m1.toUserId 
    GROUP BY sentDate, MessageID 
) 

線的東西?

+0

在我的情況下,Id是GUID - [Id] UNIQUEIDENTIFIER DEFAULT(newid())NOT NULL –

+0

所以我不能使用Max函數。而且,你的代碼在關鍵字'SELECT'附近有一個錯誤的語法。 Msg 102,Level 15,State 1,Line 14 ')'附近語法不正確。 –

+0

對不起,我可能無法訪問你的表,也不能訪問你選擇的SQL引擎。 –

1

與Gordon Linoff的回答非常相似。我剛剛爲用戶id = 1(fromto)添加了一個過濾器。我把這個查詢放在你的SQL Fiddle

ROW_NUMBER將所有行分割爲對話,然後從最新的(由createdAt排序)開始,爲對話中的每一行分配連續的數字。

WITH 
CTE 
AS 
(
    SELECT 
     M.Id 
     ,M.fromUser 
     ,M.toUser 
     ,M.message 
     ,M.createdAt 
     ,ROW_NUMBER() OVER (
      PARTITION BY 
       CASE WHEN M.fromUser < M.toUser THEN M.fromUser ELSE M.toUser END, 
       CASE WHEN M.fromUser > M.toUser THEN M.fromUser ELSE M.toUser END 
      ORDER BY M.createdAt DESC) AS rn 
    FROM Messages AS M 
    WHERE 
     M.fromUser = 1 
     OR M.toUser = 1 
) 
SELECT 
    CTE.Id 
    ,CTE.fromUser 
    ,CTE.toUser 
    ,CTE.message 
    ,CTE.createdAt 
FROM CTE 
WHERE rn = 1 
ORDER BY fromUser, toUser; 
+0

很好的解決方案。謝謝。 –