北京SEO

mysql GROUP BY 与 ORDER BY数据排序问题

2019/10/10/17:37:41  阅读:1999  来源:谷歌SEO算法  标签: 自学SEO

在做一个数据分组查询时发现我们要出来的数据不是最新版本,结果我再利用GROUP BY 与 ORDER BY数据排序但还不是最新的数据,那么要如何解决呢.

有两个解决方法:

1,where+group by(对小组进行排序)

2,从form返回的数据下手脚(即用子查询)

由where+group by的解决方法:对group by里的小组进行排序的函数我只查到group_concat()可以进行排序,但group_concat的作用是将小组里的字段里的值进行串联起来,代码如下:

select group_concat(id order by `date` desc) from `test` group by category_id

再改进一下,代码如下:

select * from `test` where id in(select SUBSTRING_INDEX(group_concat(id order by `date` desc),',',1) from `test` group by category_id ) order by `date` desc

子查询解决方案,代码如下:

select * from (select * from `test` order by `date` desc) `temp` group by category_id order by `date` desc

自己例子,代码如下:

  1. SELECT*
  2. FROM(
  3. SELECT*
  4. FROM`ecm_copy_goods_change`
  5. ORDERBY`cid`DESC
  6. )`ecm_copy_goods_change`
  7. GROUPBYgoods_id
  8. ORDERBY`cid`DESC

一个dz论坛使用调最后发布内容的案例分析:

在使用mysql排序的时候会想到按照降序分组来获得一组数据,而使用order by往往得到的不是理想中的结果,那么怎么才能使用group by 和order by得到理想中的数据结果呢?

例如有一个 帖子的回复表,posts(id,tid,subject,message,dateline),id为 自动增长字段,tid为该回复的主题帖子的id(外键关联),subject 为回复标题,message 为回复内容,dateline 为回复时间,用UNIX 时间戳表示,现在要求 选出 前十个来自不同主题的最新回复,代码如下:

SELECT * FROM posts GROUP BY tid LIMIT 10

这样一个sql语句选出来的并非你想要的 最新的回复,而是最早的回复,实际上是某篇主题的第一条回复记录.

也就是说 GROUP BY 语句没有排序,那么怎么才能让 GROUP 按照 dateline 倒序排列呢?加上 order by 子句?

看下面,代码如下:

SELECT * FROM posts GROUP BY tid ORDER BY dateline DESC LIMIT 10

这条语句选出来的结果和上面的完全一样,不过把结果倒序排列了,而选择出来的每一条记录仍然是上面的记录,原因是 group by 会比 order by 先执行,这样也就没有办法将 group by 之前,也就是在分组之前进行排序了,有网友会写出下面的sql 语句:

SELECT * FROM posts GROUP BY tid DESC ORDER BY dateline DESC LIMIT 10

也就是说 在 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 LIMIT 10

心想这样我就可以在分组前按照 dateline 倒序排列了,其实这个语句并没有起到按照tid分组的作用,原因还是上面的,在group by 字段后加 desc 还是 asc 是错误的写法,而这种写法 网友本意是想 按照 tid 分组,并且在分组的时候按照 dateline排倒序!而实际这句相当于下面的写法,去掉 GROUP BY 字段后面的 DESC,代码如下:

SELECT * FROM posts GROUP BY tid , dateline ORDER BY dateline DESC LIMIT 10

也就是说,按照 tid 和 dateline 联合分组,只有在记录tid和dateline 同时相等的时候才归纳到一组,这显然不可能,因为 dateline 时间线基本上是唯一的!

有人写出下面的语句:

SELECT *,max(dateline) as max_line FROM posts GROUP BY tid ORDER BY dateline DESC LIMIT 10

这条语句的没错是选出了最大发布时间,但是你可以对比一下 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 LIMIT 10

这条语句的预期结果和想象中的并不相同!因为你会发现,分组的结果中大量的记录没有了!为什么?因为 HAVING 是在分组的时候执行的,也就说:在分组的时候加上一个这样的条件:选择出来的 dateline 要和 本组最大的dateline 相等,执行的结果和下面的语句相同:

SELECT *,max(dateline) as max_line FROM posts GROUP BY tid HAVING count(*)=1 ORDER BY dateline DESC LIMIT 10 //phpfensi.com

看了这条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 LIMIT 10

广告内容

mysql GROUP BY 与 ORDER BY数据排序问题 mysql GROUP BY 与 ORDER BY数据排序问题 mysql GROUP BY 与 ORDER BY数据排序问题

相关阅读

热门评论

昝辉Zac 昝辉Zac

Zac的SEO博客,坚持12年,优化成为生活。

总篇数171

精选文章

RMAN中catalog和nocatalog区别介绍 小技巧:为Linux下的文件分配多个权限 zimbra8.5.1安装第三方签名ssl证书的步骤 解决mysql不能远程连接数据库方法 windows服务器mysql增量备份批处理数据库 mysql中slow query log慢日志查询分析 JavaScript跨域问题总结 Linux下负载均衡软件LVS配置(VS/DR)教程 mysql中权限参数说明 MYSQL(错误1053)无法正常启动

SEO最新算法