Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 26.8Mb
PDF (A4) - 26.9Mb
HTML Download (TGZ) - 7.1Mb
HTML Download (Zip) - 7.2Mb


MySQL 5.6 リファレンスマニュアル  /  ...  /  特定のカラムのグループごとの最大値が格納されている行

3.6.4 特定のカラムのグループごとの最大値が格納されている行

タスク: 物品ごとに最高値を付けている業者 (複数可) を調べます。

この問題は、次のようなサブクエリーを使用して解決できます。

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article);

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | C      |  1.69 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

この例では相関サブクエリーを使用していますが、これは十分でない場合があります (セクション13.2.10.7「相関サブクエリー」を参照してください)。この問題を解決する別の方法は、FROM 句または LEFT JOIN で非相関サブクエリーを使用することです。

非相関サブクエリー

SELECT s1.article, dealer, s1.price
FROM shop s1
JOIN (
  SELECT article, MAX(price) AS price
  FROM shop
  GROUP BY article) AS s2
  ON s1.article = s2.article AND s1.price = s2.price;

LEFT JOIN:

SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price
WHERE s2.article IS NULL;

LEFT JOIN の動作は、s1.price が最大値を取るときに、それより大きい値の s2.price は存在せず、s2 行の値は NULL になることに基づいています。セクション13.2.9.2「JOIN 構文」を参照してください。


User Comments
User comments in this section are, as the name implies, provided by MySQL users. The MySQL documentation team is not responsible for, nor do they endorse, any of the information provided here.
  Posted by Francisco Tirado on December 30, 2010
O T: Although that would be awesome, it did not work for me and I couldn't find it in the manual.
  Posted by Deon Kuhn on February 9, 2012
In my particular case I was only working with one record, and the correlated sub query solution proved 50% faster than the 'group by' trick. I am getting the most recent record to be altered by user 6 by way of a main table and changes log.

SELECT iA.tid
FROM main_table iA
JOIN log_table iC ON iA.tid = iC.tid AND iC.userid = 6
WHERE iC.status = 1 AND iC.id = ( SELECT MAX( id ) `scmax` FROM log_table WHERE iA.transactionID = trxid )
LIMIT 1

was faster than

SELECT iA.tid
FROM main_table iA
JOIN ( SELECT id, tid, userID FROM ( SELECT id, tid, userID FROM log_table WHERE userID = 6 ORDER BY id DESC ) iiA GROUP BY tid ) iC ON iA.tid = iC.tid AND iC.status = 1

  Posted by Daniel Bermudez on November 7, 2012
I am using this as a tutorial and tried doing it by myself before seeing the "answer" and I came up with this:

SELECT * FROM shop
WHERE price IN (SELECT MAX(price)
FROM shop GROUP BY article);

I think is very straightforward and easy to understand but I might be missing something.

Why nobody recommended this?
  Posted by Thibault Delor on November 15, 2012
@Daniel Bermudez :
You can find your query there : http://dev.mysql.com/doc/refman/5.1/en/example-maximum-row.html

"Why nobody recommended this?" :
1) it doesn't do what we want there
2) it is slow
  Posted by Predrag Bradaric on January 25, 2013
I agree with Robin Palotai. Example given by Kasey Speakman is "unreliable" in the long run.
As stated in MySQL reference manual (https://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html) values chosen by GROUP BY extension are indeterminate - it is not "guaranteed" that first row (top->down) with distinct value will be chosen in the final result.
Granted, tests have shown that (at the moment) MySQL server will choose first row (top->down) that it encounters but that can break in any future update.
  Posted by John Pratt on March 5, 2014
Perhaps a future version of MySQL will no longer be "indeterminate". It would be easier to write this query if the Select would reliably always select the top row. http://bugs.mysql.com/71942
Sign Up Login You must be logged in to post a comment.