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;
分享到:
相关推荐
根据给定的SQL Server存储过程代码片段,我们可以深入解析与SQL Server中的`GROUP BY`分组查询、存储过程以及分页技术相关的知识点。 ### SQL Server中的`GROUP BY`分组查询 `GROUP BY`子句在SQL查询语言中用于将...
在SQL中,`GROUP BY`语句用于将数据根据一个或多个列进行分类,例如在示例代码中,我们根据`A.DocNo`, `A1.Item_ItemCode`, `A2.LineNum`, `A2.ARBillLine`, `A2.Maturity`, `A2.AROCMoney_TotalMoney`和`A2....
`ORDER BY` 子句是 SQL 中用于对结果集进行排序的标准方法。它可以按照一个或多个列升序或降序排序。例如,要按 `column1` 升序排列数据: ```sql SELECT column1, column2 FROM table_name ORDER BY column1 ASC; `...
在数据库查询语言 SQL(Structured Query Language)中,`GROUP BY` 和 `ORDER BY` 是两个非常重要的子句,它们可以帮助我们更高效地管理和展示数据。 #### GROUP BY 子句 `GROUP BY` 主要用于将数据表中的数据...
除了基本的条件查询和排序,还可以结合`GROUP BY`和聚合函数(如`COUNT`、`SUM`、`AVG`、`MAX`、`MIN`)进行分组统计,或者使用`HAVING`来对分组后的结果进行过滤。 在Oracle 10g中,我们还可以使用Sql*Plus工具来...
在SQL中,分组排序问题通常涉及到数据的聚合和排名,这是数据分析和报表生成的关键步骤。本问题的目标是检索每学期每门课的学生排名情况,包括学期、课程号、学号、总评成绩以及排名,按照特定的排序规则进行输出。 ...
本篇文章将深入探讨在使用 `groupBy` 后如何正确地进行排序,以及遇到的一些常见问题和解决方法。 首先,`groupBy` 语句在 SQL 中用于将结果集按照一个或多个列进行分组,通常与聚合函数(如 `SUM`, `COUNT`, `AVG`...
`GROUP BY` 语句是 SQL 中一种常用的语句,用来对查询结果进行分组并进行聚合操作。但是,如果我们想要对分组结果进行汇总统计时,使用 `ROLLUP` 子句可以实现这一功能。 ROLLUP 子句的作用 `ROLLUP` 子句可以在 `...
在IT领域,Linux命令行是系统管理员和开发者们的强大工具,尤其在处理数据和执行...在阅读《用linux命令行实现groupby.docx》这份文档时,读者将会了解更多具体的示例和技巧,进一步提升在Linux环境下处理数据的能力。
在MySQL 8.0中,为了解决这个问题,你需要确保`ORDER BY`和`LIMIT`子句结合使用,因为`GROUP BY`不再保证按排序顺序返回结果。正确的查询可能是这样的: ```sql SELECT SwipeID, MemberID, AddTime FROM ( SELECT ...
最后,文档提到了group by子句异常问题的解决方法,即在相关操作命令后添加ORDER BY子句,以此来确保数据在进行分组之前已按照所需顺序进行了排序。这可以提升查询结果的准确性,同时也可以帮助开发者更好地理解和...
order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。 group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志...
在描述中提到的问题中,当使用`ORDER BY`对包含非唯一值的列进行排序,并结合分页查询时,发现不同页码的数据可能会有重复。这进一步证实了`ORDER BY`在Oracle中的不稳定特性。在没有唯一索引或主键约束的情况下,...
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` 是三个非常重要的子句,它们分别用于不同的数据处理操作。 1. **ORDER BY** 子句: - `ORDER BY` 用于对查询结果进行排序,按照指定的字段进行升序或降序排列。...
在`GROUP BY`查询中,我们可以使用`ORDER BY`来排序结果,但需要注意的是`ORDER BY`应用于分组后的结果,而不是原始数据。例如: ```sql SELECT 类别, SUM(数量) AS 数量之和 FROM A GROUP BY 类别 ORDER 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子句的应用剖析 GROUP BY子句是SQL语言中一个强大的工具,用于对数据进行分组并进行汇总统计。通过对GROUP BY子句的执行过程分析,阐述了使用GROUP BY子句对数据进行分组的意义,并进一步剖析了...
综上所述,`GROUP BY`和`HAVING`在Oracle数据库中是用于数据统计和分析的重要工具,正确理解并掌握它们的用法对于编写有效的SQL查询至关重要。通过合理运用这两者,数据库管理员可以生成满足各种复杂业务需求的报表...