首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 查找各商品最高價經銷商:四種 SQL 寫法性能大比拼

     編輯:MySQL 資料庫相關知識

表 shop(article, dealer, price),需求:每種商品(article)的最高價及對應經銷商(dealer)。

測試數據

article | dealer | price
0001    | A      | 3.45
0001    | B      | 3.99  ← 最高
0002    | A      | 10.99 ← 最高
0003    | B      | 1.45
0003    | C      | 1.69  ← 最高
0003    | D      | 1.25
0004    | D      | 19.95 ← 最高

寫法對比

#SQL原理MySQL 版本支持備註
1SELECT article, MAX(price) FROM shop GROUP BY article僅聚合價格,無法直接取 dealer(MySQL ONLY_FULL_GROUP_BY 下報錯)所有不完整
2SELECT article, MAX(price), dealer FROM shop GROUP BY articleMySQL 允許非聚合列,但 dealer 取值不確定(來自組內任意行)5.7 前 / 關閉 ONLY_FULL_GROUP_BY不可靠
3SELECT s1.article, s1.dealer, s1.price FROM shop s1 WHERE price = (SELECT MAX(s2.price) FROM shop s2 WHERE s1.article=s2.article)相關子查詢,語義精確所有索引 (article,price) 時較快
4SELECT s1.article, s1.dealer, s1.price FROM shop s1 JOIN (SELECT article, MAX(price) AS price FROM shop GROUP BY article) s2 ON s1.article=s2.article AND s1.price=s2.price派生表 JOIN,可利用索引、無相關子查詢開銷所有推薦
5SELECT s1.* FROM shop s1 LEFT JOIN shop s2 ON s1.article=s2.article AND s1.price < s2.price WHERE s2.article IS NULL「無更高價」反向過濾所有性能一般

最佳實踐

  1. 建立組合索引:CREATE INDEX idx_article_price ON shop(article, price);
  2. 優先使用 寫法 4(派生表 JOIN):可讀、可索引、無版本限制。
  3. MySQL 8.0+ 可用窗口函數:
    SELECT article, dealer, price FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY article ORDER BY price DESC) rn FROM shop) t WHERE rn=1;

避坑

  • 寫法 2 在 ONLY_FULL_GROUP_BY=ON(5.7+ 默認開啟)下直接報錯。
  • 子查詢未命中索引時,大表性能災難;EXPLAIN 觀察 DEPENDENT SUBQUERY vs DERIVED。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved