您当前的位置: 首页 > 数据库教程 > MySQL教程 > Mysql group by 排序问题

Mysql group by 排序问题

作者:不详 来源:网络 发布时间: 2011-06-21 13:53 点击:
类如有一个帖子的回复表,posts(id,tid,subject,message,dateline), id为自动增长字段,tid为该回复的主题帖子的id(外键关联),subject为回复标题,message为回复内容,dateline为回复时间,用UNIX时间戳表示, 现在要求选出前十个来自不同主题的最新回复 SELECT*FR

Mysql group by 排序问题

  类如有一个帖子的回复表,posts(id,tid,subject,message,dateline),
  
  id为自动增长字段,tid为该回复的主题帖子的id(外键关联),subject为回复标题,message为回复内容,dateline为回复时间,用UNIX时间戳表示,
  
  现在要求选出前十个来自不同主题的最新回复
  
  SELECT*FROM posts GROUP BY tid LIMIT10
  
  这样一个sql语句选出来的并非你想要的最新的回复,而是最早的回复,实际上是某篇主题的第一条回复记录!
  
  也就是说GROUP BY语句没有排序,那么怎么才能让GROUP按照dateline倒序排列呢?加上order by子句?
  
  看下面:
  
  SELECT*FROM posts GROUP BY tid ORDER BY dateline DESC LIMIT10
  
  这条语句选出来的结果和上面的完全一样,不过把结果倒序排列了,而选择出来的每一条记录仍然是上面的记录,原因是group by会比order by先执行,这样也就没有办法将group by之前,也就是在分组之前进行排序了,有网友会写出下面的sql语句:
  
  SELECT*FROM posts GROUP BY tid DESC ORDER BY dateline DESC LIMIT10
  
  也就是说在GROUP BY的字段tid后面加上递减顺序,这样不就可以取得分组时的最后回复了吗?这个语句执行结果会和上面的一模一样,这里加上DESC和ASC对执行结果没有任何影响!其实这是一个错误的语句,原因是GROUP BY之前并没有排序功能,mysql手册上面说,GROUP BY时是按照某种顺序排序的,某种顺序到底是什么顺序?其实根本没有顺序,因为按照tid分组,其实也就是说,把tid相等的归纳到一个组,这样想的话,GROUP BY tid DESC可以认为是在按照tid分组的时候,按照tid进行倒序排列,这不扯吗,既然是按照tid分组,当然是tid相等的归到一组,而这时候按照tid倒叙还是升序有个P用!
  
  于是有网友发明下面的语句:
  
  SELECT*FROM posts GROUP BY tid,dateline DESC ORDER BY dateline DESC LIMIT10
  
  心想这样我就可以在分组前按照dateline倒序排列了,其实这个语句并没有起到按照tid分组的作用,原因还是上面的,在group by字段后加desc还是asc是错误的写法,而这种写法网友本意是想按照tid分组,并且在分组的时候按照dateline排倒序!而实际这句相当于下面的写法:(去掉GROUP BY字段后面的DESC)
  
  SELECT*FROM posts GROUP BY tid,dateline ORDER BY dateline DESC LIMIT10
  
  也就是说,按照tid和dateline联合分组,只有在记录tid和dateline同时相等的时候才归纳到一组,这显然不可能,因为dateline时间线基本上是唯一的!
  
  有人写出下面的语句:
  
  SELECT*,max(dateline)as max_line FROM posts GROUP BY tid ORDER BY dateline DESC LIMIT10
  
  这条语句的没错是选出了最大发布时间,但是你可以对比一下dateline和max_dateline并不相等!(可能有相当的情况,就是分组的目标记录只有一条的时候!)
  
  为什么呢?原因很简单,这条语句相当于是在group by以后选出本组的最大的发布时间!对分组没有起到任何影响!因为SELECT子句是最后执行的!
  
  后来更有网友发明了下面的写法!
  
  SELECT*,max(dateline)as max_line FROM posts GROUP BY tid HAVING dateline=max(dateline)
  
  ORDER BY dateline DESC LIMIT10
  
  这条语句的预期结果和想象中的并不相同!因为你会发现,分组的结果中大量的记录没有了!为什么?因为HAVING是在分组的时候执行的,也就说:在分组的时候加上一个这样的条件:选择出来的dateline要和本组最大的dateline相等,执行的结果和下面的语句相同:
  
  SELECT*,max(dateline)as max_line FROM posts GROUP BY tid HAVING count(*)=1
  
  ORDER BY dateline DESC LIMIT10
  
  看了这条sql语句是不是明白了呢?
  
  dateline=max(dateline)只有在分组中的记录只有一条的时候才成立,原因很明白吧!只有一条他才会和本组的最大发布时间相等阿,(默认dateline为不重复的值)
  
  原因还是因为group by并没有排序功能,所有的这些排序功能只是错觉,所以你最终选出的dateline和max(dateline)永远不可能相等,除非本组的记录只有一条!GROUP BY在分组的时候,可能是一个一个来找的,发现有相等的tid,去掉,保留第一个发现的那一条记录,所以找出来的记录永远只是按照默认索引顺序排列的!
  
  那么说了这么多,到底有没有办法让group by执行前分组阿?有的,子查询阿!
  
  最简单的:
  
  SELECT*FROM(SELECT*FROM posts ORDER BY dateline DESC)GROUP BY tid ORDER BY dateline DESC LIMIT10
  
  也有网友利用自连接实现的,这样的效率应该比上面的子查询效率高,不过,为了简单明了,就只用这样一种了,GROUP BY没有排序功能,可能是mysql弱智的地方,也许是我还没有发现,
  
  期待高人拍砖!

分享到:
本文"Mysql group by 排序问题"由远航站长收集整理而来,仅供大家学习与参考使用。更多网站制作教程尽在远航站长站。
顶一下
(0)
0%
踩一下
(0)
0%
[点击 次] [返回上一页] [打印]
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
关于本站 - 联系我们 - 网站声明 - 友情连接- 网站地图 - 站点地图 - 返回顶部
Copyright © 2007-2013 www.yhzhan.com(远航站长). All Rights Reserved .
远航站长:为中小站长提供最佳的学习与交流平台,提供网页制作与网站编程等各类网站制作教程.
官方QQ:445490277 网站群:26680406 网站备案号:豫ICP备07500620号-4