萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 中 GROUP BY 與 ORDER BY 組合使用的陷阱與解決方案

問題背景

在開發微信線上客服系統時,需要從訊息記錄表中查詢最近聯繫的用戶。表結構包含 ID、uid、content、weid、addtime 等欄位。最初嘗試使用以下 SQL:

SELECT f.* 
FROM `enet_wechat_message` AS m
LEFT JOIN `enet_wechatfans` AS f ON m.fakeid = f.openid
    AND m.weid = 135
    AND f.weid = 135
WHERE f.fakeid IS NOT NULL
GROUP BY m.fakeid
ORDER BY m.id DESC
LIMIT 10

但結果並非預期中的「最近聯繫用戶」。

根本原因:MySQL 執行順序

MySQL 的查詢執行順序為:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。這意味著 ORDER BY 在 GROUP BY 之後執行,導致分組前的排序失效,MySQL 會從每組中任意取一行(通常是第一行),而非最新的一行。

解決方案:子查詢先排序再分組

利用子查詢先按時間倒序排列,再進行分組,即可保留每組的最新記錄:

SELECT * 
FROM (
    SELECT * 
    FROM `enet_wechat_message` 
    WHERE weid = 135
    ORDER BY `id` DESC
) `temp`
GROUP BY fakeid
ORDER BY `id` DESC
LIMIT 10

完整業務邏輯整合

結合用戶資訊表的最終查詢:

SELECT f.* 
FROM (
    SELECT * 
    FROM (
        SELECT * 
        FROM `enet_wechat_message` 
        WHERE weid = 135
        ORDER BY `id` DESC
    ) `temp`
    GROUP BY fakeid
    ORDER BY `id` DESC
    LIMIT 10
) AS m
LEFT JOIN `enet_wechatfans` AS f ON m.fakeid = f.openid
WHERE f.fakeid IS NOT NULL
GROUP BY m.fakeid
ORDER BY m.id DESC

核心要點總結

  • 執行順序決定結果:GROUP BY 先於 ORDER BY 執行,直接組合會導致排序無效。
  • 子查詢隔離排序:內層查詢先排序,外層再分組,確保每組取到最新記錄。
  • 適用場景:獲取每個用戶最新一條訊息、最新訂單、最新日誌等「分組取最新」需求。
copyright © 萬盛學電腦網 all rights reserved