`

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;

分享到:
评论

相关推荐

    sqlserver+group by分组查询分页存储过程

    根据给定的SQL Server存储过程代码片段,我们可以深入解析与SQL Server中的`GROUP BY`分组查询、存储过程以及分页技术相关的知识点。 ### SQL Server中的`GROUP BY`分组查询 `GROUP BY`子句在SQL查询语言中用于将...

    SQL Server分组排序取数据的实现

    在SQL中,`GROUP BY`语句用于将数据根据一个或多个列进行分类,例如在示例代码中,我们根据`A.DocNo`, `A1.Item_ItemCode`, `A2.LineNum`, `A2.ARBillLine`, `A2.Maturity`, `A2.AROCMoney_TotalMoney`和`A2....

    SQL 关于记录排序 sqlserver

    `ORDER BY` 子句是 SQL 中用于对结果集进行排序的标准方法。它可以按照一个或多个列升序或降序排序。例如,要按 `column1` 升序排列数据: ```sql SELECT column1, column2 FROM table_name ORDER BY column1 ASC; `...

    group by + order by

    在数据库查询语言 SQL(Structured Query Language)中,`GROUP BY` 和 `ORDER BY` 是两个非常重要的子句,它们可以帮助我们更高效地管理和展示数据。 #### GROUP BY 子句 `GROUP BY` 主要用于将数据表中的数据...

    sql查询和排序

    除了基本的条件查询和排序,还可以结合`GROUP BY`和聚合函数(如`COUNT`、`SUM`、`AVG`、`MAX`、`MIN`)进行分组统计,或者使用`HAVING`来对分组后的结果进行过滤。 在Oracle 10g中,我们还可以使用Sql*Plus工具来...

    SQL中分组排序问题

    在SQL中,分组排序问题通常涉及到数据的聚合和排名,这是数据分析和报表生成的关键步骤。本问题的目标是检索每学期每门课的学生排名情况,包括学期、课程号、学号、总评成绩以及排名,按照特定的排序规则进行输出。 ...

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

    本篇文章将深入探讨在使用 `groupBy` 后如何正确地进行排序,以及遇到的一些常见问题和解决方法。 首先,`groupBy` 语句在 SQL 中用于将结果集按照一个或多个列进行分组,通常与聚合函数(如 `SUM`, `COUNT`, `AVG`...

    group by后使用rollup子句总结

    `GROUP BY` 语句是 SQL 中一种常用的语句,用来对查询结果进行分组并进行聚合操作。但是,如果我们想要对分组结果进行汇总统计时,使用 `ROLLUP` 子句可以实现这一功能。 ROLLUP 子句的作用 `ROLLUP` 子句可以在 `...

    用Linux命令行实现SQL的groupby

    在IT领域,Linux命令行是系统管理员和开发者们的强大工具,尤其在处理数据和执行...在阅读《用linux命令行实现groupby.docx》这份文档时,读者将会了解更多具体的示例和技巧,进一步提升在Linux环境下处理数据的能力。

    My SQL group by取同组第一条

    在MySQL 8.0中,为了解决这个问题,你需要确保`ORDER BY`和`LIMIT`子句结合使用,因为`GROUP BY`不再保证按排序顺序返回结果。正确的查询可能是这样的: ```sql SELECT SwipeID, MemberID, AddTime FROM ( SELECT ...

    对Transact-SQL中groupby子句异常的分析.pdf

    最后,文档提到了group by子句异常问题的解决方法,即在相关操作命令后添加ORDER BY子句,以此来确保数据在进行分组之前已按照所需顺序进行了排序。这可以提升查询结果的准确性,同时也可以帮助开发者更好地理解和...

    sql中 order by 和 group by的区别

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

    Oracle数据库中ORDER BY排序和查询按IN条件的顺序输出

    在描述中提到的问题中,当使用`ORDER BY`对包含非唯一值的列进行排序,并结合分页查询时,发现不同页码的数据可能会有重复。这进一步证实了`ORDER BY`在Oracle中的不稳定特性。在没有唯一索引或主键约束的情况下,...

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

    SET @sql = @sql + ' GROUP BY ' + @GroupBy; SET @sql = @sql + ') AS t'; END -- 执行计算总记录数的SQL语句 EXEC sp_executesql @sql, N'@RecordCount int OUTPUT', @RecordCount OUTPUT; -- 计算总页数 ...

    sql中随机分组后的随机排序

    在SQL中实现随机分组后的随机排序是一种较为高级的数据处理技术,主要用于数据分析、报表生成等场景,能够帮助用户获得更加多样化的数据视图。本文将详细介绍如何通过SQL语句实现这一功能,并对其中涉及的关键概念和...

    order by 、group by 、having的用法

    在SQL查询中,`ORDER BY`、`GROUP BY` 和 `HAVING` 是三个非常重要的子句,它们分别用于不同的数据处理操作。 1. **ORDER BY** 子句: - `ORDER BY` 用于对查询结果进行排序,按照指定的字段进行升序或降序排列。...

    详解SQL中Group By的用法

    在`GROUP BY`查询中,我们可以使用`ORDER BY`来排序结果,但需要注意的是`ORDER BY`应用于分组后的结果,而不是原始数据。例如: ```sql SELECT 类别, SUM(数量) AS 数量之和 FROM A GROUP BY 类别 ORDER 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子句的应用剖析.pdf

    SQL语言中GROUP BY子句的应用剖析 GROUP BY子句是SQL语言中一个强大的工具,用于对数据进行分组并进行汇总统计。通过对GROUP BY子句的执行过程分析,阐述了使用GROUP BY子句对数据进行分组的意义,并进一步剖析了...

    group by的详解

    综上所述,`GROUP BY`和`HAVING`在Oracle数据库中是用于数据统计和分析的重要工具,正确理解并掌握它们的用法对于编写有效的SQL查询至关重要。通过合理运用这两者,数据库管理员可以生成满足各种复杂业务需求的报表...

Global site tag (gtag.js) - Google Analytics