2013-02-22 35 views
0

我想爲用戶獲取每個對話的最新消息。但是,我的組通過查詢似乎沒有帶回正確的行。這裏是我的數據:MySQL組通過使用MAX錯誤的結果

ID | MESSAGE | RELATED_ID | DATE_SENT 
2 | Hi  |  2  | 2013-02-21 16:03:00 
3 | Hii  |  2  | 2013-02-21 16:04:00 
4 | Hiii |  2  | 2013-02-21 16:05:00 
5 | Hiiii |  2  | 2013-02-21 16:06:00 
6 | Bye  |  6  | 2013-02-21 16:03:01 
7 | Byee |  6  | 2013-02-21 16:04:01 
8 | Byeee |  6  | 2013-02-21 16:05:01 
9 | Again |  9  | 2013-02-21 16:03:02 
10| Againn |  9  | 2013-02-21 16:04:02 

我期待的結果是:

ID | MESSAGE | RELATED_ID | DATE_SENT 
5 | Hiiii |  2  | 2013-02-21 16:06:00 
8 | Byeee |  6  | 2013-02-21 16:05:01 
10| Againn |  9  | 2013-02-21 16:04:02 

我當前的查詢是:

SELECT MAX(ID), Message, Date_Sent, related_id FROM MESSAGES GROUP BY RELATED_ID LIMIT 0,100 

,我得到的結果如下:

ID | MESSAGE | RELATED_ID | DATE_SENT 
5 | Hi  |  2  | 2013-02-21 16:03:00 
8 | Bye  |  6  | 2013-02-21 16:03:01 
10| Again |  9  | 2013-02-21 16:03:02 

它似乎得到正確的ID但不是該ID的正確數據。

我會很感激任何幫助,我可以得到這一點。

+0

GROUP BY返回第一個匹配的記錄。 – 2013-02-22 12:02:04

+1

唉!另一個毫無疑問的新SQLer被MySQL混淆了GROUP BY的非標準擴展。先進的技術與魔術無法區分,但這不是先進的技術。請閱讀:http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html – 2013-02-22 12:20:03

回答

6

您將要使用子查詢選擇max(id)每個related_id,然後加入,爲你的餐桌:

select m1.id, 
    m1.message, 
    m1.related_id, 
    m1.date_sent 
from messages m1 
inner join 
(
    select max(id) MaxId, related_id 
    from messages 
    group by related_id 
) m2 
    on m1.id = m2.MaxId 
    and m1.related_id = m2.related_id 
LIMIT 0,100 

SQL Fiddle with Demo。這樣做將確保您返回SELECT列表中其他列的正確值。當您不需要GROUP BY或聚合SELECT列表中的所有項目時,MySQL會選擇其他列的值,並且您可能會收到意外的結果。 (見MySQL Extensions to GROUP BY

從MySQL的文檔:

MySQL的擴展使用GROUP BY的,這樣的選擇列表可參考在GROUP BY子句中未命名的非聚合列。 ...您可以使用此功能通過避免不必要的列排序和分組來獲得更好的性能。但是,這非常有用,因爲每個未在GROUP BY中命名的非聚合列中的所有值對於每個組都是相同的。服務器可以自由選擇每個組中的任何值,因此除非它們相同,否則所選值是不確定的。此外,每個組的值的選擇不能通過添加ORDER BY子句來影響。結果集的排序在選擇值後發生,而ORDER BY不影響服務器選擇的值。

+0

+1,以瞭解MySQL非標準擴展錯誤特性的文檔引用。 – 2013-02-22 12:16:35

+0

+1要禁用錯誤功能,您可以設置「服務器模式」[ONLY_FULL_GROUP_BY](http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_only_full_group_by)。 – 2013-02-22 12:23:32

+0

完美地工作。感謝您解決問題+1 – 2013-02-22 14:37:11

-1

也許這應該是這樣的

取代MAX(ID)MAX(Date_Sent)

+0

OP的問題在於他使用group by子句在查詢中選擇未分組和未分組的列。雖然這在標準SQL中是被禁止的(出於很好的理由),但MySQL允許這樣做,並且經常會導致意外和不可預知的結果,例如這裏。在MySQL中,從第一條記錄返回的數據是您不應該依賴的DB-Interna。說這沒有好處,但有很大的失敗潛力。 – 2013-02-22 12:15:03

+0

@FabianBarney感謝您的指導。 – 2013-02-22 12:17:13