分组取最大值的同时获取包含最大值的行的其他字段

Achilles's picture

问题:
假设有表如下:

+---------+--------+-------+
| 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 |
|    0004 | C      |  2.97 |
+---------+--------+-------+

按article分组,求最大price,同时希望取出某article最大price时的dealer。dealer不是group by字段,标准sql里不能直接分组的同时获得该字段值。

解决办法
把dealer拼串在price后面,但是又要保证拼出来的串在比较大小时跟直接用price比较大小是一致的。

select 
	article, 
	max(concat(length(floor(price)), '-', price, '-', dealer)) as price_dealer 
from shop 
group by article;

结果:

+---------+--------------+
| article | price_dealer |
+---------+--------------+
|    0001 | 1-3.99-B     |
|    0002 | 2-10.99-A    |
|    0003 | 1-1.69-C     |
|    0004 | 2-19.95-D    |
+---------+--------------+

之后可以在程序中以'-'为分隔符进行拆分或者直接在sql中利用substring_index函数拆分:

select 
	article,
	substring_index(
		substring_index(
			max(concat(length(floor(price)),'-', price, '-', dealer)),
			'-',
			2),
		'-',
		-1) as price, 
	substring_index(
		max(concat(length(floor(price)), '-', price, '-', dealer)),
		'-', 
		-1) as dealer 
from shop 
group by article;

结果:

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

由于max()函数对字符串是按ascii排序而不是数值排序,这样'2.97'会大于'19.95'。为了得到正确的比较,我们在拼串的前面加上price整数部分的长度。

讨论:
mysql官方文档里给出了用lpad拼串排序的例子:

SELECT article,
       SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
  0.00+LEFT(      MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
FROM   shop
GROUP BY article;

运行结果和我们上面用的方法的结果一样。这种方法比较简短一些。不过需要price小数部分定长和预先知道price和dealer的最大长度。

Comments

恩,很受启发,收藏到我博客上去了,呵呵!

恩,很受启发,收藏到我博客上去了,呵呵!

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre> <font>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.