2012-12-26 113 views
2

我有一個問題從用戶之間存儲消息的表中檢索數據。 下面是表:根據第一條消息獲取最新的未讀消息

CREATE TABLE messages 
(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    sender VARCHAR(20), 
    recipient VARCHAR(30), 
    content TEXT, 
    is_read TINYINT(1), 
    created_at DATETIME, 
    PRIMARY KEY (`id`) , 
    INDEX idx_sender (sender) , 
    INDEX idx_recipient (recipient) 
); 

INSERT INTO messages (id, sender, recipient, content, is_read, created_at) 
VALUES 
-- Alice and George 
(1, 'Alice', 'George', 'Happy new year', 1, '2012-12-24 23:05:00'), 
(2, 'George', 'Alice', 'It is chrimas night...', 1, '2012-12-24 23:10:00'), 
(3, 'Alice', 'George', 'Happy Xmas then', 0, '2012-12-25 00:00:00'), 
-- John and Paul 
(4, 'John', 'Paul', 'Hi Paul', 1, '2012-12-26 09:00:00'), 
(5, 'Paul', 'John', 'Hi John', 1, '2012-12-26 09:05:00'), 
(6, 'John', 'Paul', 'Have you done this ?', 1, '2012-12-26 09:10:00'), 
(7, 'Paul', 'John', 'No I was unpacking my gifts', 0, '2012-12-26 09:05:00'), 
-- George and Tim 
(8, 'George', 'Tim', 'How was the end of the world ?', 1, '2012-12-22 10:10:00'), 
(9, 'Tim', 'George', 'Really nice !', 0, '2012-12-22 10:15:00'), 
-- John and Tim 
(10, 'John', 'Tim', 'I don\'t know if I should fire you for new year\'s eve', 1, '2012-12-27 15:20:00'), 
(11, 'Tim', 'John', 'That is a great idea!', 0, '2012-12-27 15:20:00'); 

假設喬治和約翰是經理人,和其他人是僱員。 我需要檢索管理員是收件人的最新未讀郵件。 同時,我必須只檢索那些他們也是對話發起人的消息。

那麼結果一定是:

  • 消息ID 7: '保羅', '約翰', '不,我是拆包我的禮物',0,2012-12-26 9點05分00秒
  • message id 9:'Tim','George','真的很好',0,2012-12-22 10:15:00
  • message id 11:'Tim','John','That is a ',0,2012-12-27 15:20:00

我做了一個查詢,它幾乎是,但消息id 11的行缺少:

SELECT 
    m.* 
FROM 
    messages m 
INNER JOIN (
    -- retrieve the first message (fm) 
    SELECT t.sender, t.recipient 
    FROM (
     SELECT id, sender, recipient, content, created_at, 
     IF (sender IN ('John', 'George'), sender, recipient) AS the_other 
     FROM messages 
     WHERE 
      sender IN ('John', 'George') 
      OR recipient IN ('John', 'George') 
     ORDER BY 
     created_at ASC 
    ) t 
    GROUP BY 
     the_other 
    HAVING t.sender IN ('John', 'George') 
) fm ON fm.recipient = m.sender 
    AND fm.sender = m.recipient 
WHERE 
    m.recipient IN ('John', 'George') 
    AND m.is_read = 0 
ORDER BY 
    m.created_at DESC 
LIMIT 0, 10 

由於子查詢由the_other分組,因此缺少消息ID 11。 如果我按發件人和收件人分組「發件人」,它將檢索郵件標識3,但它是不需要的行。

什麼是應該解決我的問題的SQL?

+1

做什麼你的意思是發起?爲什麼不包括記錄ID:'3'? –

+0

在啓動時,我的意思是一個對話的第一條消息是由經理髮送的,所以John或George。 記錄3不能包含,因爲在這個對話中,第一條消息是由Alice發送的,而不是由George發送的。 在我的例子中,有4個對話,愛麗絲和喬治,約翰和保羅,喬治和蒂姆,約翰和蒂姆。最後3次對話是唯一由經理髮起的對話。 – Shaolin

回答

0

下面可以使用查詢:

select a.* from 
(select id, sender, recipient, content, is_read, max(created_at) 
from message where recipent in ('John', 'George') and is_read = 0 
group by sender) a, message b (select id, sender, recipient, 
content, is_read, min(created_at) 
from message where sender in ('John', 'George') group by recipient) b 
where a.sender=b.recepient 
+0

查詢語法錯誤 –

+0

是的,我們不能選擇所有記錄通過分組只有發件人.. – Mari

+0

我fiexd您的查詢錯誤,但它給了我一個錯誤的結果:http://sqlfiddle.com/#!2/30f5a/ 7/0 – Shaolin

0

最後,我已經找到了解決辦法,但我不認爲這是最優化的查詢:

SELECT 
    m.* 
FROM 
    messages m 
INNER JOIN (
    -- retrieve the first messages (fm) 

    SELECT t.sender, t.recipient 
    FROM (
     SELECT id, sender, recipient, content, created_at, 
     IF (sender = 'John', recipient, sender) AS the_other 
     FROM messages 
     WHERE 
      sender = 'John' 
      OR recipient = 'John' 
     ORDER BY 
     created_at ASC 
    ) t 
    GROUP BY 
     the_other 
    HAVING t.sender = 'John' 

    UNION 

    SELECT t.sender, t.recipient 
    FROM (
     SELECT id, sender, recipient, content, created_at, 
     IF (sender = 'George', recipient, sender) AS the_other 
     FROM messages 
     WHERE 
      sender = 'George' 
      OR recipient = 'George' 
     ORDER BY 
     created_at ASC 
    ) t 
    GROUP BY 
     the_other 
    HAVING t.sender = 'George' 

) fm ON fm.recipient = m.sender 
    AND fm.sender = m.recipient 
WHERE 
    m.recipient IN ('John', 'George') 
    AND m.is_read = 0 
ORDER BY 
    m.created_at DESC 
LIMIT 0, 10 

http://sqlfiddle.com/#!2/30f5a/17/0