mysql的group by应用

CREATE TABLE group_test (
id TINYINT(1) UNSIGNED NOT NULL,
pubid TINYINT(1) UNSIGNED NOT NULL,
userid TINYINT(1) UNSIGNED NOT NULL,
uid TINYINT(1) NOT NULL,
msgText VARCHAR(50) NULL DEFAULT NULL,
msgTime VARCHAR(50) NULL DEFAULT NULL
)
COLLATE=’utf8_general_ci’
ENGINE=MyISAM
;
INSERT INTO group_test (id, pubid, userid, uid, msgText, msgTime) VALUES
(2, 4, 3, 1, ‘eee’, ‘2015’),
(3, 3, 1, 2, ‘abc’, ‘2015’),
(4, 3, 1, 2, ‘aaa’, ‘2015’),
(5, 3, 2, 1, ‘bbb’, ‘2015’),
(6, 3, 2, 1, ‘aaa’, ‘2015’),
(7, 3, 2, 1, ‘uuu’, ‘2015’),
(8, 5, 1, 4, ‘ooo’, ‘2015’),
(9, 5, 1, 4, ‘qaq’, ‘2015’),
(1, 4, 1, 3, ‘ddd’, ‘2015’);
条件为userid=1 or uid=1
并且以pubid进行分组
取组里最大的id并排序以id来desc
得出的结果应该为下面这3条
id pubid userid uid msgText msgTime
9 5 1 4 qaq 2015
7 3 2 1 uuu 2015
2 4 3 1 eee 2015

这里按照字面的可以写g.userid=1 or g.uid=1 group by g.pubid order by id desc
然后select max(id)即可如图
mysql的group by应用_第1张图片
但是对比下可以看到第一行和第二行是错误的
分析:
将id分别换成3和8就和插入的数据一样了,如图:

这是为什么?
我们知道常规的 sql,对于group by来说一定要结合聚合函数,而且选择的字段除了聚合函数外,还必须在group by中出现,否则报错。但是在mysql中扩展了这样的功能, 它可以將未经聚合的选择字段不出现在group by中。
对于不加聚合函数的sql来说,它的功能结合了limit来得出结果。
limit的时候得到的并不是 最大最小的值,而是某一下group by结果集中第一行,也就是相当于先group by, 然后在每个group by下面进行limit 1。

这个的含义是max是个聚合函数,但是你没有在group by出现,所以它就自作主张的随机选择了一行。这也是mysql的特点,oracle是不存在的
那应该怎样解决:
1、先得到userid=1 or uid=1并且以pubid进行分组的取组里最大的id条件的id
mysql的group by应用_第2张图片
2、用这个id与pubid再对应的表中取值
mysql的group by应用_第3张图片
来自http://bbs.csdn.net/topics/391820686

你可能感兴趣的:(mysql)