MySql先排序后去重,Group By与Order By联用,未生效解决方案!!!

探讨MySQL中按特定字段去重并选取另一字段最大值的查询难题,演示多种SQL写法及其效果,最终找到有效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

貌似MySql自身有bug?版本mysql-5.7.18-winx64

 

Create代码,带数据

-- --------------------------------------------------------
-- 主机:                           127.0.0.1
-- 服务器版本:                        5.7.18-log - MySQL Community Server (GPL)
-- 服务器操作系统:                      Win64
-- HeidiSQL 版本:                  10.3.0.5771
-- --------------------------------------------------------

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;


-- 导出 test 的数据库结构
CREATE DATABASE IF NOT EXISTS `test` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test`;

-- 导出  表 test.table1 结构
CREATE TABLE IF NOT EXISTS `table1` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '我是注释',
  `id2` int(11) DEFAULT NULL COMMENT '我是注释',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='我是注释';

-- 正在导出表  test.table1 的数据:~6 rows (大约)
/*!40000 ALTER TABLE `table1` DISABLE KEYS */;
INSERT INTO `table1` (`id`, `id2`) VALUES
	(1, 1),
	(2, 1),
	(3, 2),
	(4, 2),
	(5, 3),
	(6, 3);
/*!40000 ALTER TABLE `table1` ENABLE KEYS */;

/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

数据原型 :

需求很简单:按id2去重,取id大的那一行

目标数据:

一般写法

SELECT * FROM table1 GROUP BY id2 ORDER BY id1 desc

结果:

先聚合,后排序了,可以理解

换个写法:

SELECT * FROM table1 ORDER BY id1 desc GROUP BY id2

顺序不对,报错

二班写法

SELECT * FROM (SELECT * FROM table1 ORDER BY id DESC) tt GROUP BY id2

结果:

bug了吧??????????????

三班写法

SELECT * FROM (SELECT distinct * FROM table1 ORDER BY id DESC) tt GROUP BY id2

神奇了!

<think>好的,用户现在问的是在使用DISTINCT时,ORDER BY子句的排序字段必须出现在聚合函数参数列表中的问题。我需要理解用户的具体疑问,然后给出准确的解释。 首,用户之前的问题是关于SQL查询结果复,然后我建议他们在GROUP_CONCAT中使用DISTINCT。现在用户可能遇到了错误,比如在MySQL中使用GROUP_CONCAT时,如果ORDER BY的字段不在DISTINCT的字段中,可能会报错或者排序不生效。 接下来,我需要回忆MySQLGROUP_CONCAT函数的语法。GROUP_CONCAT的语法是GROUP_CONCAT([DISTINCT] expr [,expr ...] [ORDER BY ...] [SEPARATOR sep])。在这里,如果使用了DISTINCT,那么ORDER BY的字段必须出现在DISTINCT的expr中,否则可能会有问题。例如,如果DISTINCT是基于code,但ORDER BY用的是另个字段比如content,这时候因为DISTINCT后,可能无法正确排序,导致错误或排序不符合预期。 用户可能在实际应用时遇到了这样的错误提示,例如“ORDER BY clause is not in GROUP_CONCAT”,或者在尝试排序时结果没有按预期排列。需要解释清楚为什么会有这样的限制,以及如何正确使用。 然后,我需要给出具体的例子来说明问题。比如原查询中的GROUP_CONCAT(DISTINCT d.content ORDER BY code SEPARATOR ', '),这里DISTINCT的是d.content,但ORDER BY的是code。如果d.contentcode之间没有的关系,可能会有问题。例如,不同的code可能对应相同的content,这时候DISTINCT content后,code可能有多个值,无法确定排序的依据,导致错误。 解决方法应该是调整ORDER BY的字段,使其DISTINCT的字段致,或者确保两者有明确的关联。比如如果用户想按code排序,那么DISTINCT的时候应该同时包含codecontent,或者如果允许的话,可以只按content排序。或者,如果必须按code排序,可能需要保留code在DISTINCT中,或者对子查询进行排序,再聚合。 另外,可能需要提到MySQL的特定行为,因为不同的数据库可能有不同的处理方式。这里用户使用的是MySQL,所以需要确保解释符合MySQL的语法规则。 最后,总结问题原因解决方案,强调正确匹配DISTINCT字段ORDER BY字段的要性,并提供修改后的示例代码,帮助用户理解如何调整他们的查询。</think>--- ### **问题分析** 在 SQL 中,当使用 `GROUP_CONCAT` 的 `DISTINCT` 时,如果同时指定 `ORDER BY` 子句,**排序字段必须出现在聚合函数的参数中**,否则可能导致语法错误或逻辑矛盾。这是由 SQL 的聚合逻辑决定的。 --- ### **核心原理** 1. **`DISTINCT` 的逻辑** `DISTINCT` 会对字段,再执行后续操作。如果 `ORDER BY` 的字段不在 `DISTINCT` 的参数列表中,系统无法确定排序依据的字段是否后的数据致,从而导致逻辑冲突。 2. **MySQL 的语法规则** MySQL 要求:若在 `GROUP_CONCAT` 中同时使用 `DISTINCT` `ORDER BY`,则 **`ORDER BY` 的字段必须是 `DISTINCT` 的字段的子集**。 --- ### **具体案例** 假设原查询如下: ```sql GROUP_CONCAT(DISTINCT d.content ORDER BY code SEPARATOR ', ') ``` - **问题**:`DISTINCT` 的是 `d.content`,但 `ORDER BY` 的字段是 `code`。 - **矛盾点**: - 不同的 `code` 可能对应相同的 `content`(如 `code=1` `code=2` 都映射到 `content='Apple'`)。 - 后 `content` 唯,但 `code` 可能有多个值,此时无法确定按哪个 `code` 排序。 --- ### **解决方法** #### 1. **调整 `ORDER BY` 字段** 确保排序字段包含在 `DISTINCT` 的字段中: ```sql GROUP_CONCAT(DISTINCT d.content ORDER BY d.content SEPARATOR ', ') ``` #### 2. **同时保留 `code` `content`** 若必须按 `code` 排序,需将 `code` 包含在 `DISTINCT` 的字段中: ```sql GROUP_CONCAT(DISTINCT CONCAT(code, ':', content) ORDER BY code SEPARATOR ', ') ``` #### 3. **排序后去(子查询)** 通过子查询排序,再合并: ```sql GROUP_CONCAT(DISTINCT content SEPARATOR ', ') AS ay_content -- 子查询中已预排序 FROM ( SELECT j.id, d.content FROM SplitCTE j LEFT JOIN dm d ON j.code = d.code ORDER BY j.code ) AS sorted_data ``` --- ### **总结** - **根本原因**:`DISTINCT` 字段 `ORDER BY` 排序字段的逻辑范围不致。 - **关键规则**:在 `GROUP_CONCAT` 中,若同时使用 `DISTINCT` `ORDER BY`,排序字段必须是被的字段或其直接关联。 - **建议方案**:根据业务需求调整排序字段或合并逻辑,确保数据致性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上海好程序员

给上海好程序员加个鸡腿!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值