2015-05-26 27 views
1

我有這個SQL表Messages其中相關的條目是sender,,timestamptext。因此,例如一些例子是如何獲取最近創建的行,其中幾列中的某一列具有特定值?

sender  recipient text    timestamp 
user1  user2  hey    1 
user2  user1  hello back  2 
user1  user3  hey other dude 3 

而爲了填充像iMessage例如圖。我需要一個SQL查詢,用於給定用戶獲取用戶正在進行的每個對話中最近的消息。所以,目前我有什麼是

SELECT * 
FROM Messages m 
WHERE m.timestamp IN (SELECT MAX(m2.timestamp) 
       FROM Messages m2 
       WHERE m.sender = :user OR m.recipient = :user 
       GROUP BY sender, recipient) 

但不幸的是這個查詢返回的信息的全部3個以上因爲嵌套選擇組前兩個,即使他們都在同一個會話是分開。有沒有一種簡單的方法來表達我真正想要的SQL,最好是不創建Conversations表並進行某種連接業務?

+1

簡單查詢?沒有不是真的。對話表將是一個好主意。否則[請參閱我的答案](http://stackoverflow.com/questions/29799891/finding-latest-message-from-table-grouped-by-user-in-mysql/29800974#29800974)。它基本上是同一個問題 –

+0

什麼是「id」?我認爲這是你的消息PK,你忘了它在你的表結構中)。 –

+0

這是MySQL,對吧? – Strawberry

回答

0

在這裏,在外部查詢您要比較 「m.id」 與內部查詢,而不是使用 「m.id」 你應該使用 「m.timestamp

SELECT * 
FROM Messages m 
WHERE m.timestamp IN (SELECT max(m2.timestamp) 
        FROM Messages m2 
        WHERE m.sender = :user 
         OR m.recipient = :user) 

+1

即使它不會給出體面的結果,因爲兩個不同人之間的消息可以同時發送。 –

+0

好pala_然後我編輯了下面的查詢,你可以測試它,讓我知道 –

+0

你不能這樣做。什麼是'(選擇ID(選擇最大(.....'應該完成?除了未知的列錯誤?因爲我發佈反對的問題,[這個答案](http://stackoverflow.com/questions/) 29799891 /發現最新消息從表中分組由用戶在mysql/29800974#29800974)顯示了這樣做的工作方法 –

-1

如果您想找到用戶的最後一條消息試試這個:

SELECT * 
FROM `Messages` 
WHERE `recipient` = :user OR `sender` = :user 
ORDER BY `timestamp` DESC 
LIMIT 1 

如果你想找到最後的消息之間的兩個用戶嘗試這個辦法:

SELECT * 
FROM `Messages` 
WHERE 
    :user1 + :user2 = 
    CASE WHEN `recipient` = :user1 THEN `recipient` 
     WHEN `sender` = :user1 THEN `sender` 
     ELSE NULL 
    END + 
    CASE WHEN `recipient` = :user2 THEN `recipient` 
     WHEN `sender` = :user2 THEN `sender` 
     ELSE NULL 
    END 
ORDER BY `timestamp` DESC 
LIMIT 1 
+0

是的,mysql不支持'top'。 –

+0

@pala_謝謝我將它改爲'LIMIT';)。 –

0

你的方法在很大程度上是不可行的。現在你正在檢查WHERE m.id IN (SELECT MAX(m2.timestamp)這顯然不起作用。

假設它是一個錯字,並且您打算檢查WHERE m.timestamp IN ...它仍然不可靠,因爲來自不同對話的多條消息可能具有相同的時間戳。

相反,讓我們放棄這種方法,因爲它充滿了困難,我們只需執行anti-join即可。

select m.* 
    from messages m 
    left join messages m2 
     on ((m.sender = m2.sender and m.recipient = m2.recipient) 
      or (m.sender = m2.recipient and m.recipient = m2.sender)) 
     and m.timestamp < m2.timestamp 
    where m2.sender is null 

demo here

通過連接在兩個條件下,我們基本上加入關於「對話」,無論是發送者和接收者是否是相同的,或者一個的發送者是其他的接收器。我們的最終謂詞有一個時間範圍 - 當不存在具有較高時間戳的消息時,外部聯接將返回空值,因此我們篩選where子句中的那些(這是反聯接

相關問題