2017-09-05 166 views
-1

我有一個表,它包含從用戶a到用戶b(以及更多用戶)的消息,反之亦然。具有不同行值的多列組

我想從用戶之間的任何對話中檢索最後一條消息,另外我想按消息時間降序排列。

我的表看起來像這樣:

+--------+----------+--------------+------------------+ 
| userid | touserid | messsagetime |  message  | 
+--------+----------+---------------+------------------+ 
|  1 |  2 | 1504637613197 | hello   | 
|  1 |  2 | 1504637938942 | how are you?  | 
|  2 |  1 | 1504637970246 | i'm fine thanks. | 
|  3 |  1 | 1504640245930 | hello   | 
|  1 |  3 | 1504640322756 | hello!   | 
+--------+----------+---------------+------------------+ 

預期輸出:

+--------+----------+---------------+------------------+ 
| userid | touserid | messsagetime |  message  | 
+--------+----------+---------------+------------------+ 
|  2 |  1 | 1504637970246 | i'm fine thanks. | 
|  1 |  3 | 1504640322756 | hello!   | 
+--------+----------+---------------+------------------+` 

不幸的是,我的MySQL知識是有限的,這是因爲據我得到:

SELECT * 
    FROM 
    (SELECT * 
     FROM messages 
     WHERE userid = 1 
      or touserid = 1 
     ORDER 
      BY messagetime desc 
    ) AS a 
GROUP 
    BY userid 

哪個訂購它的消息時間,只有1條消息from - to,但不會將來自其他用戶的消息分組在一起。

爲樣本數據創建/插入:

CREATE TABLE IF NOT EXISTS `1` ( `id` int(11) NOT NULL 
AUTO_INCREMENT, `touser` int(11) NOT NULL, `fromuser` int(11) NOT 
NULL, `messagetime` bigint(20) NOT NULL, `message` text COLLATE 
utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB 
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=6 ; 


INSERT INTO `1` (`id`, `touser`, `fromuser`, `messagetime`, `message`) 
VALUES (1, 1, 2, 1504637613197, 'hello'), (2, 1, 2, 1504637938942, 
'how are you? '), (3, 2, 1, 1504637970246, 'i''m fine thanks.'), (4, 
3, 1, 1504640245930, 'hello'), (5, 1, 3, 1504640322756, 'hello!'); 

是否有任何MySQL的魔力,將實現什麼,我想在這裏做什麼?

+0

提供創建和插入語句將有助於更快地爲其中的某個人解決此問題 –

+0

從user1到user2的最後一條消息應該發生什麼? – RiggsFolly

+0

@RiggsFolly它們不應該被返回,因爲從user2到user1的消息已經在以後發送。 – user327685

回答

1

有可能以更快的方式,但是這是我的第一關: http://rextester.com/FCQU57469

我們使用工會切換touserid和fromuserId所以我們可以找出兩個人之間的「對話」。然後,我們只需獲取每個配對的最大時間戳。然後,我們將其加入到時間和用戶ID在一個或另一箇中的基礎集。這部分可能會很慢。應該注意的是,如果用戶A和B在不同的日期或年份進行對話......只有兩者之間的最新內容纔會被返回。

SELECT x.* 
FROM (SELECT max(messageTime) mmt, A, B 
     FROM (SELECT touser A, fromuser B, messageTime 
      FROM SO46062696 
      UNION ALL 
      SELECT fromuser A, touser B, messageTime 
      FROM SO46062696) Z 
     WHERE A < B 
     GROUP BY A,B 
    ) Y 
INNER JOIN SO46062696 x 
on Y.mmt = x.messagetime 
and Y.A in (x.touser, x.fromuser) 
and Y.B in (x.touser, x.fromuser) 

具有低於#的線條可能是把TOUSER = 1

  • 在Z子集必須有它的工會之前兩個聲明的地方。這對我來說是表現的理想場所,但我不確定它會給你後面的結果,因爲它只看Touser1。
  • 但也許你的意思是FromUser = 1或touser = 1,在這種情況下,它可能是理想的,它需要放在集合Y的where子句中的聯合之後。兩者都在下面說明

這個例子:http://rextester.com/CFO21487顯示,其中A < B and Z.a=1 它是什麼,我認爲你是後;用戶標識1參與(來往或來自)的所有對話以及他們與唯一對方的最近對話。在這種情況下,請考慮下面的USERId,而不要使用from或reference。

SELECT x.* 
FROM (SELECT max(messageTime) mmt, A, B 
     FROM (SELECT touser A, fromuser B, messageTime 
      FROM SO46062696 
      #WHERE touser = 1 #Prefered1 
      UNION ALL 
      SELECT fromuser A, touser B, messageTime 
      FROM SO46062696 
      #WHERE touser=1 #Prefered1) Z 
     WHERE A < B 
     # and Z.A = 1 #added Less Optimal 
     GROUP BY A,B 
    ) Y 

INNER JOIN SO46062696 x 
on Y.mmt = x.messagetime 
and Y.A in (x.touser, x.fromuser) 
and Y.B in (x.touser, x.fromuser) 

可能還有更優化的方法;但我需要了解userID 1的含義,因爲userID不是數據集中的列。

+0

謝謝你的努力。我不太確定'WHERE'語句在查詢中的位置。比方說'userId ='1''? – user327685

+0

經過更新以提供Z子集內的兩個地方是最好的,但它必須在兩個選擇上進行。還添加了一個rextester示例,以便您可以使用它。然而,這可能不會給你想要的結果我不確定你是什麼意思的userID = 1,所以它可能會更好之後A xQbert

+0

注意我的別名可能是清潔器。我很匆忙,沒有考慮好名字,你可能想重新考慮A,B,X,Y,Z和更清晰的名稱。 – xQbert