在MySQL我们经常会用到count,max,min这些函数,但是在使用这些函数的时候你确定你写的sql一定正确吗?话不多说,我们来个需求。
假设现在有一张消费表如下:
CREATE TABLE `tb_user_consume` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned DEFAULT NULL,
`goods_id` int(11) unsigned DEFAULT NULL,
`goods_name` varchar(50) CHARACTER SET utf8mb4 DEFAULT NULL,
`price` decimal(10,2) unsigned DEFAULT NULL,
`num` int(10) unsigned DEFAULT NULL,
`total` decimal(10,2) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `uq_user_good` (`user_id`,`goods_id`),
KEY `ind_total` (`total`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
现在我们需要取出每个用户购买最多的商品名。看似一个很简单的需求,基本上都能在脑海里想出来下面的SQL。
SELECT max(num),user_id,goods_name FROM tb_user_consume GROUP BY user_id LIMIT 10;
从语句上面看,好像没有什么问题都满足需求,我们执行下来验证下。
返回的结果如下:
max(num) user_id goods_name
982 1000000 1号商品
898 1000001 1号商品
982 1000002 1号商品
883 1000003 1号商品
706 1000004 1号商品
940 1000005 1号商品
761 1000006 1号商品
958 1000007 1号商品
739 1000008 1号商品
967 1000009 1号商品
感觉有点不对劲,难道1号商品这么畅销吗?大家都是买1号商品,我们来看下原始数据。
id user_id goods_id goods_name price num total
1 1000000 1 1号商品 1.30 982 1276.60
2 1000000 2 2号商品 1.15 212 243.80
3 1000000 3 3号商品 3.40 356 1210.40
4 1000000 4 4号商品 18.99 974 18496.26
5 1000000 5 5号商品 7.40 760 5624.00
6 1000001 1 1号商品 1.30 25 32.50
7 1000001 2 2号商品 1.15 898 1032.70
8 1000001 3 3号商品 3.40 743 2526.20
9 1000001 4 4号商品 18.99 311 5905.89
10 1000001 5 5号商品 7.40 732 5416.80
11 1000002 1 1号商品 1.30 982 1276.60
12 1000002 2 2号商品 1.15 674 775.10
13 1000002 3 3号商品 3.40 378 1285.20
14 1000002 4 4号商品 18.99 285 5412.15
15 1000002 5 5号商品 7.40 519 3840.60
我们很清楚的看出来了,1000001 购买的商品是2号商品居多,结合上面的查询结果来看,max(num)似乎没有问题,那么出问题似乎的是在goods_name的显示上。
查下网上的教程查询的结果集都只会包含group的那一列,和max的结果值。
那么我们还得自己来想解决办法,做一个子查询先按照user_id分组取出最大的num值,创建临时表和源表用user_id和num查询,于是就有了下面的SQL。
SELECT a.user_id,a.`goods_name`,a.num FROM tb_user_consume a JOIN (SELECT user_id , max(num) AS num FROM tb_user_consume where user_id < 1000010 GROUP BY user_id) b ON a.user_id = b.user_id AND a.num = b.num;
查询结果为
user_id goods_name num
1000000 1号商品 982
1000001 2号商品 898
1000002 1号商品 982
1000003 3号商品 883
1000004 5号商品 706
1000005 1号商品 940
1000006 3号商品 761
1000007 3号商品 958
1000008 4号商品 739
1000009 5号商品 967
对比数据发现查询结果准确无误。所以千万不能偷懒使用简单的使用max查询其他列。
