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)即可如图
但是对比下可以看到第一行和第二行是错误的
分析:
将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
2、用这个id与pubid再对应的表中取值
来自http://bbs.csdn.net/topics/391820686