`

sql group by排序问题

阅读更多
mysql group by排序问题2009-08-28 16:37
类如 有一个 帖子的回复表,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


看了这条sql语句是不是明白了呢?

dateline=max(dateline) 只有在分组中的记录只有一条的时候才成立,原因很明白吧!只有一条他才会和本组的最大发布时间相等阿,(默认dateline为不重复的值)


原因还是因为 group by 并没有排序功能,所有的这些排序功能只是错觉,所以你最终选出的 dateline 和max(dateline) 永远不可能相等,除非本组的记录只有一条!GROUP BY 在分组的时候,可能是一个一个来找的,发现有相等的tid,去掉,保留第一个发现的那一条记录,所以找出来的 记录永远只是按照默认索引顺序排列的!


那么说了这么多,到底有没有办法让 group by 执行前分组阿?有的 ,子查询阿!


最简单的 :


SELECT cid, aid, title, stitle, image, author, postdate FROM news_content WHERE aid IN(SELECT DISTINCT aid FROM cate_links where cid='3') AND status=0 ORDER BY postdate DESC

limit 10


SELECT distinct n.cid, n.aid, n.title, n.stitle, n.image, n.author, n.postdate FROM news_content n, cate_links c WHERE c.cid=3 AND n.aid=c.aid AND n.status=0 ORDER BY n.postdate

DESC limit 10 比上面的快

select *,concat(aid,cid) as ac from cate_links where cid='3'; 1135
select *,concat(aid,cid) as ac from cate_links where cid='3' group by ac;            721
SELECT * FROM cate_links where cid='3' group by concat(aid,cid) 721
select max(autoid),concat(aid,cid) as ac from cate_links where cid='3' group by ac; 721
select max(autoid) from cate_links where cid='3' group by concat(aid,cid);           721

select *,max(autoid) from cate_links where cid='3' group by concat(aid,cid) HAVING autoid=max(autoid);         356
select * from cate_links where cid='3' group by concat(aid,cid) HAVING autoid=max(autoid);                     356
SELECT aid FROM (SELECT * FROM cate_links as a where cid='3' order by autoid DESC) as b group by concat(aid,cid) 721


delete from cate_links where autoid not IN (SELECT autoid FROM (SELECT * FROM cate_links as a where cid='3' order by autoid DESC) as b group by concat(aid,cid)); 11秒
delete from cate_links where autoid not IN (SELECT autoid FROM (SELECT * FROM cate_links as a order by autoid DESC) as b group by concat(aid,cid)); 非常慢
delete from cate_links e where autoid !=(select min(autoid) as mid from cate_links a where a.aid=e.aid and a.cid=e.cid); 错误
delete from cate_links e where autoid !=(select(select min(autoid) from cate_links a where a.aid=e.aid and a.cid=e.cid) as tmp); 错误
delete from cate_links where autoid not in (select mid from (select min(autoid) as mid from cate_links a group by concat(aid,cid)) b);是对的,很快

ALTER TABLE `cate_links` ADD UNIQUE `aid_2` ( `aid` , `cid` );
show create table cate_links;

分享到:
评论

相关推荐

    浅谈laravel框架sql中groupBy之后排序的问题

    今天小编就为大家分享一篇浅谈laravel框架sql中groupBy之后排序的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    sql中 order by 和 group by的区别

    order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。 group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志...

    深入解析mysql中order by与group by的顺序问题

    mysql 中order by 与group by的顺序是:selectfromwheregroup byorder by注意:group by 比order by先执行,order by不会对group by 内部进行排序,如果group by后只有一条记录,那么order by 将无效。要查出group ...

    深入浅析SQL中的group by 和 having 用法

    一、sql中的group by 用法解析:  Group By语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”。  作用:通过一定的规则将一个数据集划分成若干个小的区域,然后针对若干个小区域进行数据处理...

    mysql分组取每组前几条记录(排名) 附group by与order by的研究

    –按某一字段分组取最大(小)值所在行的数据 代码如下: /* 数据如下: nameval memo a 2 a2(a的第二个值) a 1 a1–a的第一个值 a 3 a3:a的第三个值 b 1 b1–b的第一个值 b 3 b3:b的第三个值 b 2 b2b2b2b2 b 4 b4b4 b ...

    【mysql知识点整理】— order by 、group by 出现Using filesort原因详解

    文章目录测试数据1 sql执行顺序2 order by 和 group by什么时候会出现Using filesort — 理论3 order by 和 group by什么时候会出现Using filesort — 实践3.1 不会出现 Using filesort的情况 — 符合最佳左前缀法则...

    详解partition by和group by对比

    今天大概弄懂了partition by和group by的区别联系。 1. group by是分组函数,...3.partition by相比较于group by,能够在保留全部数据的基础上,只对其中某些字段做分组排序(类似excel中的操作),而group by则只

    Server2005高效分页存储过程(支持多字段排序,支持Group By)

    Server2005/2008专用高效分页存储过程(支持多字段排序,支持Group By分组).

    sql语句生成器+支持各大数据库+说明书

    排序(Order By) 条件(Where) 分组(Group By) 分组条件(Having) 计算字段 SQL查询表 SQL查询子句 丰富的函数 表别名 字段别名(包括计算字段和非计算字段) 联合(Union,对于Oracle 支持Union All,Minus,Intersect) ...

    SQL语言生成器(delphi)

    排序(Order By) 条件(Where) 分组(Group By) 分组条件(Having) 计算字段 SQL查询表 SQL查询子句 丰富的函数 表别名 字段别名(包括计算字段和非计算字段) 联合(Union,对于Oracle 支持Union All,Minus,Intersect) 4、...

    mysql中order by与group by的区别

    order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是... 您可能感兴趣的文章:sql中 order by 和 group by的区别深度分析mysql GROUP BY 与 ORDER BYgroup by,having,o

    SQL数据排序与分组

     二、GROUP BY子句  语法:   SELECT column1,column2 FROM table1,table2 WHERE conditions GROUP BY column1,column2 ORDER BY column1,column2;  1、分组函数...

    sql语句重复操作

    选择重复,消除重复和选择出序列 所有名字重复人的记录是: select * from emp where name in (select name from emp group by name having count(*)>1)

    SQL语句自动生成工具

    无需安装和卸载 支持几乎所有的SQL语法: 排序(Order By) 条件(Where) 分组(Group By) 分组条件(Having) 计算字段 SQL查询表 SQL查询子句 丰富的函数 表别名 字段别名(包括计算...

    SQL实验:使用分组,排序和聚合函数以及连接查询

    使用分组,排序和聚合函数以及连接查询 1.掌握通配符的用法 2.掌握 GROUP BY 子句的使用 3.掌握 ORDER BY子句的使用 4.掌握 DISTINCT关键字的使用 5.掌握聚集函数的使用

    SQL语句生成及分析器

    排序(Order By) 条件(Where) 分组(Group By) 分组条件(Having) 计算字段 SQL查询表 SQL查询子句 丰富的函数 表别名 字段别名 联合(Union,Union All,Minus,Intersect) 4、SQL语句反向分析 无论多么复杂...

    SQL语法教材.pdf

    SELECT 语法基本架构 =============================== SELECT 字段 1, 字段 2, … 字段 n FROM 表格 1, 表格 2, … 表格 n WHERE 条件 GROUP BY 字段 1, 字段 2, … 字段 n ORDER BY 字段 1, 字段 2, … 字段 n ==...

    SQL语句生成及分析器(中文绿色)

    3.4 分组 (Group By) 3.5 组内条件 (Having) 3.6 排序 (Order By) 3.7 数据表的内连接、外连接 3.7.1 SQL 92 标准:Inner Join、Left Join、Right Join、Full Join, 3.7.2 特殊语法:*=、=*、*=*(MS_SQL,...

    T-SQL高级查询

    select count(*), (sex * id) new from student where id > 2 group by sex * id order by sex * id; --group by all 所有分组 按照年龄分组,是所有的年龄 select count(*), age from student group by all age; ...

    精通SQL--结构化查询语言详解

    9.4.3 order by子句排序union运算结果 180 9.4.4 对多表进行union运算 181 9.4.5 union join 连接表 183 9.5 表连接的其他应用及注意问题 183 9.5.1 连接表进行聚合运算 183 9.5.2 多表连接的综合运用 185 ...

Global site tag (gtag.js) - Google Analytics